]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/libdrm.git/commitdiff
libdrm: add mode setting files
authorJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 17 Dec 2008 18:09:49 +0000 (10:09 -0800)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 17 Dec 2008 18:11:37 +0000 (10:11 -0800)
Add mode setting files to libdrm, including xf86drmMode.* and the new
drm_mode.h header.  Also add a couple of tests to sanity check the
kernel interfaces and update code to support them.

20 files changed:
libdrm/Makefile.am
libdrm/intel/intel_bufmgr.h
libdrm/intel/intel_bufmgr_gem.c
libdrm/xf86drm.c
libdrm/xf86drm.h
libdrm/xf86drmMode.c [new file with mode: 0644]
libdrm/xf86drmMode.h [new file with mode: 0644]
linux-core/drm_mode.h [new symlink]
shared-core/Makefile.am
shared-core/drm.h
shared-core/drm_mode.h [new file with mode: 0644]
tests/Makefile.am
tests/dristat.c
tests/modeprint/Makefile [new file with mode: 0644]
tests/modeprint/app [new file with mode: 0755]
tests/modeprint/modeprint.c [new file with mode: 0644]
tests/modeprint/test [new file with mode: 0644]
tests/modetest/Makefile [new file with mode: 0644]
tests/modetest/modetest.c [new file with mode: 0644]
tests/modetest/test [new file with mode: 0644]

index a5be36e0220c08a84087a253c693bc5a5a722ea7..eb63abe10a8cee711d55ab43a7c453dd449fb843 100644 (file)
@@ -26,9 +26,10 @@ libdrm_la_LDFLAGS = -version-number 2:4:0 -no-undefined
 
 AM_CFLAGS = -I$(top_srcdir)/shared-core
 libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \
+       xf86drmMode.c libdrm_lists.h
        libdrm_lists.h
 
 libdrmincludedir = ${includedir}
-libdrminclude_HEADERS = xf86drm.h
+libdrminclude_HEADERS = xf86drm.h xf86drmMode.h
 
 EXTRA_DIST = ChangeLog TODO
index f134f169aa0c6646d0f288fe152582aa05198b15..e8c2e063c416488a8bd4a6ccdb87c97566e31050 100644 (file)
@@ -66,6 +66,11 @@ struct _drm_intel_bo {
 
     /** Buffer manager context associated with this buffer object */
     drm_intel_bufmgr *bufmgr;
+
+    /**
+     * MM-specific handle for accessing object
+     */
+    int handle;
 };
 
 drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
index e5a1375eced15926e00f2c317e9ed88e5d22cfb9..9605cc7c73a181448bbf7405cad7cde1be72201e 100644 (file)
@@ -351,6 +351,7 @@ drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
 
        ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
        bo_gem->gem_handle = create.handle;
+       bo_gem->bo.handle = bo_gem->gem_handle;
        if (ret != 0) {
            free(bo_gem);
            return NULL;
index c36f1964dba520832933cdc67f7f210aa115a0f1..0b5d31fef57ad7c45fe1dabb9ca711f5dc8dcac4 100644 (file)
@@ -87,6 +87,9 @@
 
 #define DRM_MSG_VERBOSITY 3
 
+#define DRM_NODE_CONTROL 0
+#define DRM_NODE_RENDER 1
+
 static drmServerInfoPtr drm_server_info;
 
 void drmSetServerInfo(drmServerInfoPtr info)
@@ -174,7 +177,7 @@ static char *drmStrdup(const char *s)
 /**
  * Call ioctl, restarting if it is interupted
  */
-static int
+int
 drmIoctl(int fd, unsigned long request, void *arg)
 {
     int        ret;
@@ -277,7 +280,7 @@ static int drmMatchBusID(const char *id1, const char *id2)
  * special file node with the major and minor numbers specified by \p dev and
  * parent directory if necessary and was called by root.
  */
-static int drmOpenDevice(long dev, int minor)
+static int drmOpenDevice(long dev, int minor, int type)
 {
     stat_t          st;
     char            buf[64];
@@ -287,7 +290,7 @@ static int drmOpenDevice(long dev, int minor)
     uid_t           user    = DRM_DEV_UID;
     gid_t           group   = DRM_DEV_GID, serv_group;
     
-    sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+    sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
     drmMsg("drmOpenDevice: node name is %s\n", buf);
 
     if (drm_server_info) {
@@ -386,15 +389,15 @@ wait_for_udev:
  * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
  * name from \p minor and opens it.
  */
-static int drmOpenMinor(int minor, int create)
+static int drmOpenMinor(int minor, int create, int type)
 {
     int  fd;
     char buf[64];
     
     if (create)
-       return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
+       return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
     
-    sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+    sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
     if ((fd = open(buf, O_RDWR, 0)) >= 0)
        return fd;
     return -errno;
@@ -417,7 +420,7 @@ int drmAvailable(void)
     int           retval = 0;
     int           fd;
 
-    if ((fd = drmOpenMinor(0, 1)) < 0) {
+    if ((fd = drmOpenMinor(0, 1, DRM_NODE_RENDER)) < 0) {
 #ifdef __linux__
        /* Try proc for backward Linux compatibility */
        if (!access("/proc/dri/0", R_OK))
@@ -458,7 +461,7 @@ static int drmOpenByBusid(const char *busid)
 
     drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
     for (i = 0; i < DRM_MAX_MINOR; i++) {
-       fd = drmOpenMinor(i, 1);
+       fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
        drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
        if (fd >= 0) {
            sv.drm_di_major = 1;
@@ -520,7 +523,7 @@ static int drmOpenByName(const char *name)
      * already in use.  If it's in use it will have a busid assigned already.
      */
     for (i = 0; i < DRM_MAX_MINOR; i++) {
-       if ((fd = drmOpenMinor(i, 1)) >= 0) {
+       if ((fd = drmOpenMinor(i, 1, DRM_NODE_RENDER)) >= 0) {
            if ((version = drmGetVersion(fd))) {
                if (!strcmp(version->name, name)) {
                    drmFreeVersion(version);
@@ -564,7 +567,7 @@ static int drmOpenByName(const char *name)
                        if (*pt) { /* Found busid */
                            return drmOpenByBusid(++pt);
                        } else { /* No busid */
-                           return drmOpenDevice(strtol(devstring, NULL, 0),i);
+                           return drmOpenDevice(strtol(devstring, NULL, 0),i, DRM_NODE_RENDER);
                        }
                    }
                }
@@ -614,6 +617,10 @@ int drmOpen(const char *name, const char *busid)
     return -1;
 }
 
+int drmOpenControl(int minor)
+{
+    return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
+}
 
 /**
  * Free the version information returned by drmGetVersion().
@@ -2434,3 +2441,20 @@ void drmCloseOnce(int fd)
        }
     }
 }
+
+int drmSetMaster(int fd)
+{
+       int ret;
+
+       fprintf(stderr,"Setting master \n");
+       ret = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
+       return ret;
+}
+
+int drmDropMaster(int fd)
+{
+       int ret;
+       fprintf(stderr,"Dropping master \n");
+       ret = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
+       return ret;
+}
index f4fa71b0f8e92867dfef503a0c8b2624bb80f7f8..f9dd1bfcc532d25588de1cba33d7f44203b5ffc6 100644 (file)
@@ -49,6 +49,7 @@
 
 #define DRM_DIR_NAME  "/dev/dri"
 #define DRM_DEV_NAME  "%s/card%d"
+#define DRM_CONTROL_DEV_NAME  "%s/controlD%d"
 #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
 
 #define DRM_ERR_NO_DEVICE  (-1001)
@@ -74,6 +75,7 @@ typedef struct drmHashEntry {
     void     *tagTable;
 } drmHashEntry;
 
+extern int drmIoctl(int fd, unsigned long request, void *arg);
 extern void *drmGetHashTable(void);
 extern drmHashEntry *drmGetEntry(int fd);
 
@@ -508,6 +510,7 @@ do {        register unsigned int __old __asm("o0");                \
 /* General user-level programmer's API: unprivileged */
 extern int           drmAvailable(void);
 extern int           drmOpen(const char *name, const char *busid);
+extern int drmOpenControl(int minor);
 extern int           drmClose(int fd);
 extern drmVersionPtr drmGetVersion(int fd);
 extern drmVersionPtr drmGetLibVersion(int fd);
@@ -659,4 +662,7 @@ extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened);
 extern void drmCloseOnce(int fd);
 extern void drmMsg(const char *format, ...);
 
+extern int drmSetMaster(int fd);
+extern int drmDropMaster(int fd);
+
 #endif
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
new file mode 100644 (file)
index 0000000..f481428
--- /dev/null
@@ -0,0 +1,686 @@
+/*
+ * \file xf86drmMode.c
+ * Header for DRM modesetting interface.
+ *
+ * \author Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * \par Acknowledgements:
+ * Feb 2007, Dave Airlie <airlied@linux.ie>
+ */
+
+/*
+ * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie>
+ * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * TODO the types we are after are defined in diffrent headers on diffrent
+ * platforms find which headers to include to get uint32_t
+ */
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+
+#include "xf86drmMode.h"
+#include "xf86drm.h"
+#include <drm.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+
+#define U642VOID(x) ((void *)(unsigned long)(x))
+#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
+
+/*
+ * Util functions
+ */
+
+void* drmAllocCpy(void *array, int count, int entry_size)
+{
+       char *r;
+       int i;
+
+       if (!count || !array || !entry_size)
+               return 0;
+
+       if (!(r = drmMalloc(count*entry_size)))
+               return 0;
+
+       for (i = 0; i < count; i++)
+               memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
+
+       return r;
+}
+
+/*
+ * A couple of free functions.
+ */
+
+void drmModeFreeModeInfo(struct drm_mode_modeinfo *ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr);
+}
+
+void drmModeFreeResources(drmModeResPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr);
+
+}
+
+void drmModeFreeFB(drmModeFBPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       /* we might add more frees later. */
+       drmFree(ptr);
+}
+
+void drmModeFreeCrtc(drmModeCrtcPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr);
+
+}
+
+void drmModeFreeConnector(drmModeConnectorPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr->modes);
+       drmFree(ptr);
+
+}
+
+void drmModeFreeEncoder(drmModeEncoderPtr ptr)
+{
+       drmFree(ptr);
+}
+
+/*
+ * ModeSetting functions.
+ */
+
+drmModeResPtr drmModeGetResources(int fd)
+{
+       struct drm_mode_card_res res;
+       drmModeResPtr r = 0;
+
+       memset(&res, 0, sizeof(struct drm_mode_card_res));
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
+               return 0;
+
+       if (res.count_fbs)
+               res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
+       if (res.count_crtcs)
+               res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
+       if (res.count_connectors)
+               res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
+       if (res.count_encoders)
+               res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
+               r = NULL;
+               goto err_allocs;
+       }
+
+       /*
+        * return
+        */
+
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return 0;
+
+       r->min_width     = res.min_width;
+       r->max_width     = res.max_width;
+       r->min_height    = res.min_height;
+       r->max_height    = res.max_height;
+       r->count_fbs     = res.count_fbs;
+       r->count_crtcs   = res.count_crtcs;
+       r->count_connectors = res.count_connectors;
+       r->count_encoders = res.count_encoders;
+       /* TODO we realy should test if these allocs fails. */
+       r->fbs           = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
+       r->crtcs         = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
+       r->connectors       = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
+       r->encoders      = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
+
+err_allocs:
+       drmFree(U642VOID(res.fb_id_ptr));
+       drmFree(U642VOID(res.crtc_id_ptr));
+       drmFree(U642VOID(res.connector_id_ptr));
+       drmFree(U642VOID(res.encoder_id_ptr));
+
+       return r;
+}
+
+int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
+                 uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
+                uint32_t *buf_id)
+{
+       struct drm_mode_fb_cmd f;
+       int ret;
+
+       f.width  = width;
+       f.height = height;
+       f.pitch  = pitch;
+       f.bpp    = bpp;
+       f.depth  = depth;
+       f.handle = bo_handle;
+
+       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
+               return ret;
+
+       *buf_id = f.fb_id;
+       return 0;
+}
+
+int drmModeRmFB(int fd, uint32_t bufferId)
+{
+       return drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
+
+
+}
+
+drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
+{
+       struct drm_mode_fb_cmd info;
+       drmModeFBPtr r;
+
+       info.fb_id = buf;
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info))
+               return NULL;
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return NULL;
+
+       r->fb_id = info.fb_id;
+       r->width = info.width;
+       r->height = info.height;
+       r->pitch = info.pitch;
+       r->bpp = info.bpp;
+       r->handle = info.handle;
+       r->depth = info.depth;
+
+       return r;
+}
+
+
+/*
+ * Crtc functions
+ */
+
+drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
+{
+       struct drm_mode_crtc crtc;
+       drmModeCrtcPtr r;
+
+       crtc.crtc_id = crtcId;
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
+               return 0;
+
+       /*
+        * return
+        */
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return 0;
+
+       r->crtc_id         = crtc.crtc_id;
+       r->x               = crtc.x;
+       r->y               = crtc.y;
+       r->mode_valid      = crtc.mode_valid;
+       if (r->mode_valid)
+               memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
+       r->buffer_id       = crtc.fb_id;
+       r->gamma_size      = crtc.gamma_size;
+       return r;
+}
+
+
+int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
+                   uint32_t x, uint32_t y, uint32_t *connectors, int count,
+                  struct drm_mode_modeinfo *mode)
+{
+       struct drm_mode_crtc crtc;
+
+       crtc.x             = x;
+       crtc.y             = y;
+       crtc.crtc_id       = crtcId;
+       crtc.fb_id         = bufferId;
+       crtc.set_connectors_ptr = VOID2U64(connectors);
+       crtc.count_connectors = count;
+       if (mode) {
+         memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
+         crtc.mode_valid = 1;
+       } else
+         crtc.mode_valid = 0;
+
+       return drmIoctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
+}
+
+/*
+ * Cursor manipulation
+ */
+
+int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
+{
+       struct drm_mode_cursor arg;
+
+       arg.flags = DRM_MODE_CURSOR_BO;
+       arg.crtc_id = crtcId;
+       arg.width = width;
+       arg.height = height;
+       arg.handle = bo_handle;
+
+       return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
+}
+
+int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
+{
+       struct drm_mode_cursor arg;
+
+       arg.flags = DRM_MODE_CURSOR_MOVE;
+       arg.crtc_id = crtcId;
+       arg.x = x;
+       arg.y = y;
+
+       return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
+}
+
+/*
+ * Encoder get
+ */
+drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
+{
+       struct drm_mode_get_encoder enc;
+       drmModeEncoderPtr r = NULL;
+
+       enc.encoder_id = encoder_id;
+       enc.encoder_type = 0;
+       enc.possible_crtcs = 0;
+       enc.possible_clones = 0;
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
+               return 0;
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return 0;
+
+       r->encoder_id = enc.encoder_id;
+       r->crtc_id = enc.crtc_id;
+       r->encoder_type = enc.encoder_type;
+       r->possible_crtcs = enc.possible_crtcs;
+       r->possible_clones = enc.possible_clones;
+
+       return r;
+}
+
+/*
+ * Connector manipulation
+ */
+
+drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
+{
+       struct drm_mode_get_connector conn;
+       drmModeConnectorPtr r = NULL;
+
+       conn.connector_id = connector_id;
+       conn.connector_type_id = 0;
+       conn.connector_type  = 0;
+       conn.count_modes  = 0;
+       conn.modes_ptr    = 0;
+       conn.count_props  = 0;
+       conn.props_ptr    = 0;
+       conn.prop_values_ptr = 0;
+       conn.count_encoders  = 0;
+       conn.encoders_ptr = 0;
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
+               return 0;
+
+       if (conn.count_props) {
+               conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
+               conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
+       }
+
+       if (conn.count_modes)
+               conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
+
+       if (conn.count_encoders)
+               conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
+               goto err_allocs;
+
+       if(!(r = drmMalloc(sizeof(*r)))) {
+               goto err_allocs;
+       }
+
+       r->connector_id = conn.connector_id;
+       r->encoder_id = conn.encoder_id;
+       r->connection   = conn.connection;
+       r->mmWidth      = conn.mm_width;
+       r->mmHeight     = conn.mm_height;
+       r->subpixel     = conn.subpixel;
+       r->count_modes  = conn.count_modes;
+       /* TODO we should test if these alloc & cpy fails. */
+       r->count_props  = conn.count_props;
+       r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
+       r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
+       r->modes        = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
+       r->count_encoders = conn.count_encoders;
+       r->encoders     = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
+       r->connector_type  = conn.connector_type;
+       r->connector_type_id = conn.connector_type_id;
+
+       if (!r->props || !r->prop_values || !r->modes || !r->encoders)
+               goto err_allocs;
+
+err_allocs:
+       drmFree(U642VOID(conn.prop_values_ptr));
+       drmFree(U642VOID(conn.props_ptr));
+       drmFree(U642VOID(conn.modes_ptr));
+       drmFree(U642VOID(conn.encoders_ptr));
+
+       return r;
+}
+
+int drmModeAttachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
+{
+       struct drm_mode_mode_cmd res;
+
+       memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
+       res.connector_id = connector_id;
+
+       return drmIoctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
+}
+
+int drmModeDetachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
+{
+       struct drm_mode_mode_cmd res;
+
+       memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
+       res.connector_id = connector_id;
+
+       return drmIoctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
+}
+
+
+drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
+{
+       struct drm_mode_get_property prop;
+       drmModePropertyPtr r;
+
+       prop.prop_id = property_id;
+       prop.count_enum_blobs = 0;
+       prop.count_values = 0;
+       prop.flags = 0;
+       prop.enum_blob_ptr = 0;
+       prop.values_ptr = 0;
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
+               return 0;
+
+       if (prop.count_values)
+               prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
+
+       if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
+               prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
+
+       if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
+               prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
+               prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
+       }
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
+               r = NULL;
+               goto err_allocs;
+       }
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return NULL;
+
+       r->prop_id = prop.prop_id;
+       r->count_values = prop.count_values;
+
+       r->flags = prop.flags;
+       if (prop.count_values)
+               r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
+       if (prop.flags & DRM_MODE_PROP_ENUM) {
+               r->count_enums = prop.count_enum_blobs;
+               r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
+       } else if (prop.flags & DRM_MODE_PROP_BLOB) {
+               r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
+               r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
+               r->count_blobs = prop.count_enum_blobs;
+       }
+       strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
+       r->name[DRM_PROP_NAME_LEN-1] = 0;
+
+err_allocs:
+       drmFree(U642VOID(prop.values_ptr));
+       drmFree(U642VOID(prop.enum_blob_ptr));
+
+       return r;
+}
+
+void drmModeFreeProperty(drmModePropertyPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr->values);
+       drmFree(ptr->enums);
+       drmFree(ptr);
+}
+
+drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
+{
+       struct drm_mode_get_blob blob;
+       drmModePropertyBlobPtr r;
+
+       blob.length = 0;
+       blob.data = 0;
+       blob.blob_id = blob_id;
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+               return NULL;
+
+       if (blob.length)
+               blob.data = VOID2U64(drmMalloc(blob.length));
+
+       if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
+               r = NULL;
+               goto err_allocs;
+       }
+
+       if (!(r = drmMalloc(sizeof(*r))))
+               return NULL;
+
+       r->id = blob.blob_id;
+       r->length = blob.length;
+       r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
+
+err_allocs:
+       drmFree(U642VOID(blob.data));
+       return r;
+}
+
+void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       drmFree(ptr->data);
+       drmFree(ptr);
+}
+
+int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
+                            uint64_t value)
+{
+       struct drm_mode_connector_set_property osp;
+       int ret;
+
+       osp.connector_id = connector_id;
+       osp.prop_id = property_id;
+       osp.value = value;
+
+       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
+               return ret;
+
+       return 0;
+}
+
+/*
+ * checks if a modesetting capable driver has attached to the pci id
+ * returns 0 if modesetting supported.
+ *  -EINVAL or invalid bus id
+ *  -ENOSYS if no modesetting support
+*/
+int drmCheckModesettingSupported(const char *busid)
+{
+#ifdef __linux__
+       char pci_dev_dir[1024];
+       int domain, bus, dev, func;
+       DIR *sysdir;
+       struct dirent *dent;
+       int found = 0, ret;
+
+       ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
+       if (ret != 4)
+               return -EINVAL;
+
+       sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
+               domain, bus, dev, func);
+
+       sysdir = opendir(pci_dev_dir);
+       if (sysdir) {
+               dent = readdir(sysdir);
+               while (dent) {
+                       if (!strncmp(dent->d_name, "controlD", 8)) {
+                               found = 1;
+                               break;
+                       }
+
+                       dent = readdir(sysdir);
+               }
+               closedir(sysdir);
+               if (found)
+                       return 0;
+       }
+
+       sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
+               domain, bus, dev, func);
+
+       sysdir = opendir(pci_dev_dir);
+       if (!sysdir)
+               return -EINVAL;
+
+       dent = readdir(sysdir);
+       while (dent) {
+               if (!strncmp(dent->d_name, "drm:controlD", 12)) {
+                       found = 1;
+                       break;
+               }
+
+               dent = readdir(sysdir);
+       }
+
+       closedir(sysdir);
+       if (found)
+               return 0;
+#endif
+       return -ENOSYS;
+
+}
+
+int drmModeReplaceFB(int fd, uint32_t buffer_id,
+                    uint32_t width, uint32_t height, uint8_t depth,
+                    uint8_t bpp, uint32_t pitch, uint32_t bo_handle)
+{
+       struct drm_mode_fb_cmd f;
+       int ret;
+
+       f.width = width;
+       f.height = height;
+       f.pitch = pitch;
+       f.bpp = bpp;
+       f.depth = depth;
+       f.handle = bo_handle;
+       f.fb_id = buffer_id;
+
+       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_REPLACEFB, &f)))
+               return ret;
+
+       return 0;
+}
+
+int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
+                       uint16_t *red, uint16_t *green, uint16_t *blue)
+{
+       int ret;
+       struct drm_mode_crtc_lut l;
+
+       l.crtc_id = crtc_id;
+       l.gamma_size = size;
+       l.red = VOID2U64(red);
+       l.green = VOID2U64(green);
+       l.blue = VOID2U64(blue);
+
+       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l)))
+               return ret;
+
+       return 0;
+}
+
+int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
+                       uint16_t *red, uint16_t *green, uint16_t *blue)
+{
+       int ret;
+       struct drm_mode_crtc_lut l;
+
+       l.crtc_id = crtc_id;
+       l.gamma_size = size;
+       l.red = VOID2U64(red);
+       l.green = VOID2U64(green);
+       l.blue = VOID2U64(blue);
+
+       if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l)))
+               return ret;
+
+       return 0;
+}
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
new file mode 100644 (file)
index 0000000..965b7be
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * \file xf86drmMode.h
+ * Header for DRM modesetting interface.
+ *
+ * \author Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * \par Acknowledgements:
+ * Feb 2007, Dave Airlie <airlied@linux.ie>
+ */
+
+/*
+ * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie>
+ * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <drm.h>
+
+/*
+ * This is the interface for modesetting for drm.
+ *
+ * In order to use this interface you must include either <stdint.h> or another
+ * header defining uint32_t, int32_t and uint16_t.
+ *
+ * It aims to provide a randr1.2 compatible interface for modesettings in the
+ * kernel, the interface is also ment to be used by libraries like EGL.
+ *
+ * More information can be found in randrproto.txt which can be found here:
+ * http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git
+ *
+ * There are some major diffrences to be noted. Unlike the randr1.2 proto you
+ * need to create the memory object of the framebuffer yourself with the ttm
+ * buffer object interface. This object needs to be pinned.
+ */
+
+typedef struct _drmModeRes {
+
+       int count_fbs;
+       uint32_t *fbs;
+
+       int count_crtcs;
+       uint32_t *crtcs;
+
+       int count_connectors;
+       uint32_t *connectors;
+
+       int count_encoders;
+       uint32_t *encoders;
+
+       uint32_t min_width, max_width;
+       uint32_t min_height, max_height;
+} drmModeRes, *drmModeResPtr;
+
+typedef struct drm_mode_fb_cmd drmModeFB, *drmModeFBPtr;
+
+typedef struct _drmModePropertyBlob {
+       uint32_t id;
+       uint32_t length;
+       void *data;
+} drmModePropertyBlobRes, *drmModePropertyBlobPtr;
+
+typedef struct _drmModeProperty {
+       uint32_t prop_id;
+       uint32_t flags;
+       char name[DRM_PROP_NAME_LEN];
+       int count_values;
+       uint64_t *values; // store the blob lengths
+       int count_enums;
+       struct drm_mode_property_enum *enums;
+       int count_blobs;
+       uint32_t *blob_ids; // store the blob IDs
+} drmModePropertyRes, *drmModePropertyPtr;
+
+typedef struct _drmModeCrtc {
+       uint32_t crtc_id;
+       uint32_t buffer_id; /**< FB id to connect to 0 = disconnect */
+
+       uint32_t x, y; /**< Position on the framebuffer */
+       uint32_t width, height;
+       int mode_valid;
+       struct drm_mode_modeinfo mode;
+
+       int gamma_size; /**< Number of gamma stops */
+
+} drmModeCrtc, *drmModeCrtcPtr;
+
+typedef struct _drmModeEncoder {
+       uint32_t encoder_id;
+       uint32_t encoder_type;
+       uint32_t crtc_id;
+       uint32_t possible_crtcs;
+       uint32_t possible_clones;
+} drmModeEncoder, *drmModeEncoderPtr;
+
+typedef enum {
+       DRM_MODE_CONNECTED         = 1,
+       DRM_MODE_DISCONNECTED      = 2,
+       DRM_MODE_UNKNOWNCONNECTION = 3
+} drmModeConnection;
+
+typedef enum {
+       DRM_MODE_SUBPIXEL_UNKNOWN        = 1,
+       DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2,
+       DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3,
+       DRM_MODE_SUBPIXEL_VERTICAL_RGB   = 4,
+       DRM_MODE_SUBPIXEL_VERTICAL_BGR   = 5,
+       DRM_MODE_SUBPIXEL_NONE           = 6
+} drmModeSubPixel;
+
+typedef struct _drmModeConnector {
+       uint32_t connector_id;
+       uint32_t encoder_id; /**< Encoder currently connected to */
+       uint32_t connector_type;
+       uint32_t connector_type_id;
+       drmModeConnection connection;
+       uint32_t mmWidth, mmHeight; /**< HxW in millimeters */
+       drmModeSubPixel subpixel;
+
+       int count_modes;
+       struct drm_mode_modeinfo *modes;
+
+       int count_props;
+       uint32_t *props; /**< List of property ids */
+       uint64_t *prop_values; /**< List of property values */
+
+       int count_encoders;
+       uint32_t *encoders; /**< List of encoder ids */
+} drmModeConnector, *drmModeConnectorPtr;
+
+
+
+extern void drmModeFreeModeInfo( struct drm_mode_modeinfo *ptr );
+extern void drmModeFreeResources( drmModeResPtr ptr );
+extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
+extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
+extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
+
+/**
+ * Retrives all of the resources associated with a card.
+ */
+extern drmModeResPtr drmModeGetResources(int fd);
+
+/*
+ * FrameBuffer manipulation.
+ */
+
+/**
+ * Retrive information about framebuffer bufferId
+ */
+extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+
+/**
+ * Creates a new framebuffer with an buffer object as its scanout buffer.
+ */
+extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
+                       uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
+                       uint32_t *buf_id);
+/**
+ * Destroies the given framebuffer.
+ */
+extern int drmModeRmFB(int fd, uint32_t bufferId);
+
+/**
+ * Replace a framebuffer object with a new one - for resizing the screen.
+ */
+extern int drmModeReplaceFB(int fd, uint32_t buffer_id,
+                           uint32_t width, uint32_t height, uint8_t depth,
+                           uint8_t bpp, uint32_t pitch, uint32_t bo_handle);
+
+/*
+ * Crtc functions
+ */
+
+/**
+ * Retrive information about the ctrt crtcId
+ */
+extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId);
+
+/**
+ * Set the mode on a crtc crtcId with the given mode modeId.
+ */
+int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
+                   uint32_t x, uint32_t y, uint32_t *connectors, int count,
+                  struct drm_mode_modeinfo *mode);
+
+/*
+ * Cursor functions
+ */
+
+/**
+ * Set the cursor on crtc
+ */
+int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height);
+
+/**
+ * Move the cursor on crtc
+ */
+int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y);
+
+/**
+ * Encoder functions
+ */
+drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id);
+
+/*
+ * Connector manipulation
+ */
+
+/**
+ * Retrive information about the connector connectorId.
+ */
+extern drmModeConnectorPtr drmModeGetConnector(int fd,
+               uint32_t connectorId);
+
+/**
+ * Attaches the given mode to an connector.
+ */
+extern int drmModeAttachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info);
+
+/**
+ * Detaches a mode from the connector
+ * must be unused, by the given mode.
+ */
+extern int drmModeDetachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info);
+
+extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId);
+extern void drmModeFreeProperty(drmModePropertyPtr ptr);
+
+extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
+extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
+extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
+                                   uint64_t value);
+extern int drmCheckModesettingSupported(const char *busid);
+
+extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
+                              uint16_t *red, uint16_t *green, uint16_t *blue);
+extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
+                              uint16_t *red, uint16_t *green, uint16_t *blue);
diff --git a/linux-core/drm_mode.h b/linux-core/drm_mode.h
new file mode 120000 (symlink)
index 0000000..a43f138
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/drm_mode.h
\ No newline at end of file
index 7193e5271a94ae9f2b2b6904347245decd4fb4b1..99e90d641a683c9d49df0a0af8dd37114003ecb5 100644 (file)
@@ -25,6 +25,7 @@
 klibdrmincludedir = ${includedir}/drm
 klibdrminclude_HEADERS = \
                          drm.h \
+                         drm_mode.h \
                          drm_sarea.h \
                          i915_drm.h \
                          mach64_drm.h \
index 507f047897495a0fb354455dad013f82ce7e2f43..b97ba0987b64c7f8f50b53065ccf719ff1adf533 100644 (file)
@@ -985,6 +985,8 @@ struct drm_gem_open {
        uint64_t size;
 };
 
+#include "drm_mode.h"
+
 /**
  * \name Ioctls Definitions
  */
@@ -1027,6 +1029,9 @@ struct drm_gem_open {
 #define DRM_IOCTL_SET_SAREA_CTX                DRM_IOW( 0x1c, struct drm_ctx_priv_map)
 #define DRM_IOCTL_GET_SAREA_CTX                DRM_IOWR(0x1d, struct drm_ctx_priv_map)
 
+#define DRM_IOCTL_SET_MASTER            DRM_IO(0x1e)
+#define DRM_IOCTL_DROP_MASTER           DRM_IO(0x1f)
+
 #define DRM_IOCTL_ADD_CTX              DRM_IOWR(0x20, struct drm_ctx)
 #define DRM_IOCTL_RM_CTX               DRM_IOWR(0x21, struct drm_ctx)
 #define DRM_IOCTL_MOD_CTX              DRM_IOW( 0x22, struct drm_ctx)
@@ -1082,6 +1087,28 @@ struct drm_gem_open {
 #define DRM_IOCTL_BO_VERSION          DRM_IOR(0xd6, struct drm_bo_version_arg)
 #define DRM_IOCTL_MM_INFO               DRM_IOWR(0xd7, struct drm_mm_info_arg)
 
+#define DRM_IOCTL_MODE_GETRESOURCES     DRM_IOWR(0xA0, struct drm_mode_card_res)
+
+#define DRM_IOCTL_MODE_GETCRTC          DRM_IOWR(0xA1, struct drm_mode_crtc)
+#define DRM_IOCTL_MODE_SETCRTC         DRM_IOWR(0xA2, struct drm_mode_crtc)
+#define DRM_IOCTL_MODE_CURSOR          DRM_IOWR(0xA3, struct drm_mode_cursor)
+#define DRM_IOCTL_MODE_GETGAMMA                DRM_IOWR(0xA4, struct drm_mode_crtc_lut)
+#define DRM_IOCTL_MODE_SETGAMMA                DRM_IOWR(0xA5, struct drm_mode_crtc_lut)
+
+#define DRM_IOCTL_MODE_GETENCODER      DRM_IOWR(0xA6, struct drm_mode_get_encoder)
+
+#define DRM_IOCTL_MODE_GETCONNECTOR    DRM_IOWR(0xA7, struct drm_mode_get_connector)
+#define DRM_IOCTL_MODE_ATTACHMODE      DRM_IOWR(0xA8, struct drm_mode_mode_cmd)
+#define DRM_IOCTL_MODE_DETACHMODE      DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
+#define DRM_IOCTL_MODE_GETPROPERTY     DRM_IOWR(0xAA, struct drm_mode_get_property)
+#define DRM_IOCTL_MODE_SETPROPERTY     DRM_IOWR(0xAB, struct drm_mode_connector_set_property)
+#define DRM_IOCTL_MODE_GETPROPBLOB     DRM_IOWR(0xAC, struct drm_mode_get_blob)
+
+#define DRM_IOCTL_MODE_GETFB           DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
+#define DRM_IOCTL_MODE_ADDFB           DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
+#define DRM_IOCTL_MODE_RMFB            DRM_IOWR(0xAF, uint32_t)
+#define DRM_IOCTL_MODE_REPLACEFB       DRM_IOWR(0xB0, struct drm_mode_fb_cmd)
+
 /*@}*/
 
 /**
diff --git a/shared-core/drm_mode.h b/shared-core/drm_mode.h
new file mode 100644 (file)
index 0000000..601d2bd
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
+ * Copyright (c) 2007 Jakob Bornecrantz <wallbraker@gmail.com>
+ * Copyright (c) 2008 Red Hat Inc.
+ * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * Copyright (c) 2007-2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_MODE_H
+#define _DRM_MODE_H
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#else
+#include <linux/kernel.h>
+#endif
+
+#define DRM_DISPLAY_INFO_LEN   32
+#define DRM_CONNECTOR_NAME_LEN 32
+#define DRM_DISPLAY_MODE_LEN   32
+#define DRM_PROP_NAME_LEN      32
+
+#define DRM_MODE_TYPE_BUILTIN  (1<<0)
+#define DRM_MODE_TYPE_CLOCK_C  ((1<<1) | DRM_MODE_TYPE_BUILTIN)
+#define DRM_MODE_TYPE_CRTC_C   ((1<<2) | DRM_MODE_TYPE_BUILTIN)
+#define DRM_MODE_TYPE_PREFERRED        (1<<3)
+#define DRM_MODE_TYPE_DEFAULT  (1<<4)
+#define DRM_MODE_TYPE_USERDEF  (1<<5)
+#define DRM_MODE_TYPE_DRIVER   (1<<6)
+
+/* Video mode flags */
+/* bit compatible with the xorg definitions. */
+#define DRM_MODE_FLAG_PHSYNC   (1<<0)
+#define DRM_MODE_FLAG_NHSYNC   (1<<1)
+#define DRM_MODE_FLAG_PVSYNC   (1<<2)
+#define DRM_MODE_FLAG_NVSYNC   (1<<3)
+#define DRM_MODE_FLAG_INTERLACE        (1<<4)
+#define DRM_MODE_FLAG_DBLSCAN  (1<<5)
+#define DRM_MODE_FLAG_CSYNC    (1<<6)
+#define DRM_MODE_FLAG_PCSYNC   (1<<7)
+#define DRM_MODE_FLAG_NCSYNC   (1<<8)
+#define DRM_MODE_FLAG_HSKEW    (1<<9) /* hskew provided */
+#define DRM_MODE_FLAG_BCAST    (1<<10)
+#define DRM_MODE_FLAG_PIXMUX   (1<<11)
+#define DRM_MODE_FLAG_DBLCLK   (1<<12)
+#define DRM_MODE_FLAG_CLKDIV2  (1<<13)
+
+/* DPMS flags */
+/* bit compatible with the xorg definitions. */
+#define DRM_MODE_DPMS_ON       0
+#define DRM_MODE_DPMS_STANDBY  1
+#define DRM_MODE_DPMS_SUSPEND  2
+#define DRM_MODE_DPMS_OFF      3
+
+/* Scaling mode options */
+#define DRM_MODE_SCALE_NON_GPU         0
+#define DRM_MODE_SCALE_FULLSCREEN      1
+#define DRM_MODE_SCALE_NO_SCALE                2
+#define DRM_MODE_SCALE_ASPECT          3
+
+/* Dithering mode options */
+#define DRM_MODE_DITHERING_OFF 0
+#define DRM_MODE_DITHERING_ON  1
+
+struct drm_mode_modeinfo {
+       uint32_t clock;
+       uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew;
+       uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan;
+
+       uint32_t vrefresh; /* vertical refresh * 1000 */
+
+       uint32_t flags;
+       uint32_t type;
+       char name[DRM_DISPLAY_MODE_LEN];
+};
+
+struct drm_mode_card_res {
+       uint64_t fb_id_ptr;
+       uint64_t crtc_id_ptr;
+       uint64_t connector_id_ptr;
+       uint64_t encoder_id_ptr;
+       uint32_t count_fbs;
+       uint32_t count_crtcs;
+       uint32_t count_connectors;
+       uint32_t count_encoders;
+       uint32_t min_width, max_width;
+       uint32_t min_height, max_height;
+};
+
+struct drm_mode_crtc {
+       uint64_t set_connectors_ptr;
+       uint32_t count_connectors;
+
+       uint32_t crtc_id; /**< Id */
+       uint32_t fb_id; /**< Id of framebuffer */
+
+       uint32_t x, y; /**< Position on the frameuffer */
+
+       uint32_t gamma_size;
+       uint32_t mode_valid;
+       struct drm_mode_modeinfo mode;
+};
+
+#define DRM_MODE_ENCODER_NONE  0
+#define DRM_MODE_ENCODER_DAC   1
+#define DRM_MODE_ENCODER_TMDS  2
+#define DRM_MODE_ENCODER_LVDS  3
+#define DRM_MODE_ENCODER_TVDAC 4
+
+struct drm_mode_get_encoder {
+       uint32_t encoder_id;
+       uint32_t encoder_type;
+
+       uint32_t crtc_id; /**< Id of crtc */
+
+       uint32_t possible_crtcs;
+       uint32_t possible_clones;
+};
+
+/* This is for connectors with multiple signal types. */
+/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */
+#define DRM_MODE_SUBCONNECTOR_Automatic        0
+#define DRM_MODE_SUBCONNECTOR_Unknown  0
+#define DRM_MODE_SUBCONNECTOR_DVID     3
+#define DRM_MODE_SUBCONNECTOR_DVIA     4
+#define DRM_MODE_SUBCONNECTOR_Composite        5
+#define DRM_MODE_SUBCONNECTOR_SVIDEO   6
+#define DRM_MODE_SUBCONNECTOR_Component        8
+
+#define DRM_MODE_CONNECTOR_Unknown     0
+#define DRM_MODE_CONNECTOR_VGA         1
+#define DRM_MODE_CONNECTOR_DVII                2
+#define DRM_MODE_CONNECTOR_DVID                3
+#define DRM_MODE_CONNECTOR_DVIA                4
+#define DRM_MODE_CONNECTOR_Composite   5
+#define DRM_MODE_CONNECTOR_SVIDEO      6
+#define DRM_MODE_CONNECTOR_LVDS                7
+#define DRM_MODE_CONNECTOR_Component   8
+#define DRM_MODE_CONNECTOR_9PinDIN     9
+#define DRM_MODE_CONNECTOR_DisplayPort 10
+#define DRM_MODE_CONNECTOR_HDMIA       11
+#define DRM_MODE_CONNECTOR_HDMIB       12
+
+struct drm_mode_get_connector {
+
+       uint64_t encoders_ptr;
+       uint64_t modes_ptr;
+       uint64_t props_ptr;
+       uint64_t prop_values_ptr;
+
+       uint32_t count_modes;
+       uint32_t count_props;
+       uint32_t count_encoders;
+
+       uint32_t encoder_id; /**< Current Encoder */
+       uint32_t connector_id; /**< Id */
+       uint32_t connector_type;
+       uint32_t connector_type_id;
+
+       uint32_t connection;
+       uint32_t mm_width, mm_height; /**< HxW in millimeters */
+       uint32_t subpixel;
+};
+
+#define DRM_MODE_PROP_PENDING  (1<<0)
+#define DRM_MODE_PROP_RANGE    (1<<1)
+#define DRM_MODE_PROP_IMMUTABLE        (1<<2)
+#define DRM_MODE_PROP_ENUM     (1<<3) /* enumerated type with text strings */
+#define DRM_MODE_PROP_BLOB     (1<<4)
+
+struct drm_mode_property_enum {
+       uint64_t value;
+       char name[DRM_PROP_NAME_LEN];
+};
+
+struct drm_mode_get_property {
+       uint64_t values_ptr; /* values and blob lengths */
+       uint64_t enum_blob_ptr; /* enum and blob id ptrs */
+
+       uint32_t prop_id;
+       uint32_t flags;
+       char name[DRM_PROP_NAME_LEN];
+
+       uint32_t count_values;
+       uint32_t count_enum_blobs;
+};
+
+struct drm_mode_connector_set_property {
+       uint64_t value;
+       uint32_t prop_id;
+       uint32_t connector_id;
+};
+
+struct drm_mode_get_blob {
+       uint32_t blob_id;
+       uint32_t length;
+       uint64_t data;
+};
+
+struct drm_mode_fb_cmd {
+       uint32_t fb_id;
+       uint32_t width, height;
+       uint32_t pitch;
+       uint32_t bpp;
+       uint32_t depth;
+       /* driver specific handle */
+       uint32_t handle;
+};
+
+struct drm_mode_mode_cmd {
+       uint32_t connector_id;
+       struct drm_mode_modeinfo mode;
+};
+
+#define DRM_MODE_CURSOR_BO     (1<<0)
+#define DRM_MODE_CURSOR_MOVE   (1<<1)
+
+/*
+ * depending on the value in flags diffrent members are used.
+ *
+ * CURSOR_BO uses
+ *    crtc
+ *    width
+ *    height
+ *    handle - if 0 turns the cursor of
+ *
+ * CURSOR_MOVE uses
+ *    crtc
+ *    x
+ *    y
+ */
+struct drm_mode_cursor {
+       uint32_t flags;
+       uint32_t crtc_id;
+       int32_t x;
+       int32_t y;
+       uint32_t width;
+       uint32_t height;
+       /* driver specific handle */
+       uint32_t handle;
+};
+
+struct drm_mode_crtc_lut {
+       uint32_t crtc_id;
+       uint32_t gamma_size;
+
+       /* pointers to arrays */
+       uint64_t red;
+       uint64_t green;
+       uint64_t blue;
+};
+
+#endif
index 95f0f22e1d852b43e74b88c8449715f388b80edc..02b2ef0aee9be1c6da625c206af8d573ae22c638 100644 (file)
@@ -15,6 +15,10 @@ libdrmtest_la_LIBADD = \
 
 LDADD = libdrmtest.la
 
+noinst_SUBDIRS = \
+       modeprint \
+       modetest
+
 TESTS = auth \
        openclose \
        getversion \
index 89853164c7265c8a88a4ae9d3e39d9850a3dd20e..48c3b51b480b45250d52f639d56cb2dd844f6466 100644 (file)
@@ -263,7 +263,7 @@ int main(int argc, char **argv)
 
     for (i = 0; i < 16; i++) if (!minor || i == minor) {
        sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i);
-       fd = drmOpenMinor(i, 1);
+       fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
        if (fd >= 0) {
            printf("%s\n", buf);
            if (mask & DRM_BUSID)   getbusid(fd);
diff --git a/tests/modeprint/Makefile b/tests/modeprint/Makefile
new file mode 100644 (file)
index 0000000..70788dc
--- /dev/null
@@ -0,0 +1,14 @@
+
+all: app
+
+#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \
+#        -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \
+
+app: modeprint.c
+       @gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm modeprint.c
+
+clean:
+       @rm -f app
+
+run: app
+       @sudo ./test
diff --git a/tests/modeprint/app b/tests/modeprint/app
new file mode 100755 (executable)
index 0000000..82085c8
Binary files /dev/null and b/tests/modeprint/app differ
diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c
new file mode 100644 (file)
index 0000000..595d444
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * \file modedemo.c
+ * Test program to dump DRM kernel mode setting related information.
+ * Queries the kernel for all available information and dumps it to stdout.
+ *
+ * \author Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+/*
+ * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+int connectors;
+int full_props;
+int edid;
+int modes;
+int full_modes;
+int encoders;
+int crtcs;
+int fbs;
+char *module_name;
+
+const char* getConnectionText(drmModeConnection conn)
+{
+       switch (conn) {
+       case DRM_MODE_CONNECTED:
+               return "connected";
+       case DRM_MODE_DISCONNECTED:
+               return "disconnected";
+       default:
+               return "unknown";
+       }
+
+}
+
+int printMode(struct drm_mode_modeinfo *mode)
+{
+       if (full_modes) {
+               printf("Mode: %s\n", mode->name);
+               printf("\tclock       : %i\n", mode->clock);
+               printf("\thdisplay    : %i\n", mode->hdisplay);
+               printf("\thsync_start : %i\n", mode->hsync_start);
+               printf("\thsync_end   : %i\n", mode->hsync_end);
+               printf("\thtotal      : %i\n", mode->htotal);
+               printf("\thskew       : %i\n", mode->hskew);
+               printf("\tvdisplay    : %i\n", mode->vdisplay);
+               printf("\tvsync_start : %i\n", mode->vsync_start);
+               printf("\tvsync_end   : %i\n", mode->vsync_end);
+               printf("\tvtotal      : %i\n", mode->vtotal);
+               printf("\tvscan       : %i\n", mode->vscan);
+               printf("\tvrefresh    : %i\n", mode->vrefresh);
+               printf("\tflags       : %i\n", mode->flags);
+       } else {
+               printf("Mode: \"%s\" %ix%i %.0f\n", mode->name,
+                               mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000.0);
+       }
+       return 0;
+}
+
+int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, uint64_t value)
+{
+       const unsigned char *name = NULL;
+       int j;
+
+       printf("Property: %s\n", props->name);
+       printf("\tid           : %i\n", props->prop_id);
+       printf("\tflags        : %i\n", props->flags);
+       printf("\tcount_values : %d\n", props->count_values);
+
+
+       if (props->count_values) {
+               printf("\tvalues       :");
+               for (j = 0; j < props->count_values; j++)
+                       printf(" %lld", props->values[j]);
+               printf("\n");
+       }
+
+
+       printf("\tcount_enums  : %d\n", props->count_enums);
+
+       if (props->flags & DRM_MODE_PROP_BLOB) {
+               drmModePropertyBlobPtr blob;
+
+               blob = drmModeGetPropertyBlob(fd, value);
+               if (blob) {
+                       printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data);
+                       drmModeFreePropertyBlob(blob);
+               } else {
+                       printf("error getting blob %lld\n", value);
+               }
+
+       } else {
+               if (!strncmp(props->name, "DPMS", 4))
+                       ;
+
+               for (j = 0; j < props->count_enums; j++) {
+                       printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name);
+                       if (props->enums[j].value == value)
+                               name = props->enums[j].name;
+               }
+
+               if (props->count_enums && name) {
+                       printf("\tcon_value    : %s\n", name);
+               } else {
+                       printf("\tcon_value    : %lld\n", value);
+               }
+       }
+
+       return 0;
+}
+
+int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id)
+{
+       int i = 0;
+       struct drm_mode_modeinfo *mode = NULL;
+       drmModePropertyPtr props;
+
+       printf("Connector: %d-%d\n", connector->connector_type, connector->connector_type_id);
+       printf("\tid             : %i\n", id);
+       printf("\tencoder id     : %i\n", connector->encoder_id);
+       printf("\tconn           : %s\n", getConnectionText(connector->connection));
+       printf("\tsize           : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight);
+       printf("\tcount_modes    : %i\n", connector->count_modes);
+       printf("\tcount_props    : %i\n", connector->count_props);
+       if (connector->count_props) {
+               printf("\tprops          :");
+               for (i = 0; i < connector->count_props; i++)
+                       printf(" %i", connector->props[i]);
+               printf("\n");
+       }
+
+       printf("\tcount_encoders : %i\n", connector->count_encoders);
+       if (connector->count_encoders) {
+               printf("\tencoders       :");
+               for (i = 0; i < connector->count_encoders; i++)
+                       printf(" %i", connector->encoders[i]);
+               printf("\n");
+       }
+
+       if (modes) {
+               for (i = 0; i < connector->count_modes; i++) {
+                       mode = &connector->modes[i];
+                       printMode(mode);
+               }
+       }
+
+       if (full_props) {
+               for (i = 0; i < connector->count_props; i++) {
+                       props = drmModeGetProperty(fd, connector->props[i]);
+                       if (props) {
+                               printProperty(fd, res, props, connector->prop_values[i]);
+                               drmModeFreeProperty(props);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id)
+{
+       printf("Encoder\n");
+       printf("\tid     :%i\n", id);
+       printf("\tcrtc_id   :%d\n", encoder->crtc_id);
+       printf("\ttype   :%d\n", encoder->encoder_type);
+       printf("\tpossible_crtcs  :%d\n", encoder->possible_crtcs);
+       printf("\tpossible_clones :%d\n", encoder->possible_clones);
+       return 0;
+}
+
+int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id)
+{
+       printf("Crtc\n");
+       printf("\tid             : %i\n", id);
+       printf("\tx              : %i\n", crtc->x);
+       printf("\ty              : %i\n", crtc->y);
+       printf("\twidth          : %i\n", crtc->width);
+       printf("\theight         : %i\n", crtc->height);
+       printf("\tmode           : %p\n", &crtc->mode);
+       printf("\tgamma size     : %d\n", crtc->gamma_size);
+
+       return 0;
+}
+
+int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb)
+{
+       printf("Framebuffer\n");
+       printf("\thandle    : %i\n", fb->handle);
+       printf("\twidth     : %i\n", fb->width);
+       printf("\theight    : %i\n", fb->height);
+       printf("\tpitch     : %i\n", fb->pitch);;
+       printf("\tbpp       : %i\n", fb->bpp);
+       printf("\tdepth     : %i\n", fb->depth);
+       printf("\tbuffer_id : %i\n", fb->handle);
+
+       return 0;
+}
+
+int printRes(int fd, drmModeResPtr res)
+{
+       int i;
+       drmModeFBPtr fb;
+       drmModeCrtcPtr crtc;
+       drmModeEncoderPtr encoder;
+       drmModeConnectorPtr connector;
+
+       printf("Resources\n\n");
+
+       printf("count_connectors : %i\n", res->count_connectors);
+       printf("count_encoders   : %i\n", res->count_encoders);
+       printf("count_crtcs      : %i\n", res->count_crtcs);
+       printf("count_fbs        : %i\n", res->count_fbs);
+
+       printf("\n");
+
+       if (connectors) {
+               for (i = 0; i < res->count_connectors; i++) {
+                       connector = drmModeGetConnector(fd, res->connectors[i]);
+
+                       if (!connector)
+                               printf("Could not get connector %i\n", res->connectors[i]);
+                       else {
+                               printConnector(fd, res, connector, res->connectors[i]);
+                               drmModeFreeConnector(connector);
+                       }
+               }
+               printf("\n");
+       }
+
+
+       if (encoders) {
+               for (i = 0; i < res->count_encoders; i++) {
+                       encoder = drmModeGetEncoder(fd, res->encoders[i]);
+
+                       if (!encoder)
+                               printf("Could not get encoder %i\n", res->encoders[i]);
+                       else {
+                               printEncoder(fd, res, encoder, res->encoders[i]);
+                               drmModeFreeEncoder(encoder);
+                       }
+               }
+               printf("\n");
+       }
+
+       if (crtcs) {
+               for (i = 0; i < res->count_crtcs; i++) {
+                       crtc = drmModeGetCrtc(fd, res->crtcs[i]);
+
+                       if (!crtc)
+                               printf("Could not get crtc %i\n", res->crtcs[i]);
+                       else {
+                               printCrtc(fd, res, crtc, res->crtcs[i]);
+                               drmModeFreeCrtc(crtc);
+                       }
+               }
+               printf("\n");
+       }
+
+       if (fbs) {
+               for (i = 0; i < res->count_fbs; i++) {
+                       fb = drmModeGetFB(fd, res->fbs[i]);
+
+                       if (!fb)
+                               printf("Could not get fb %i\n", res->fbs[i]);
+                       else {
+                               printFrameBuffer(fd, res, fb);
+                               drmModeFreeFB(fb);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+void args(int argc, char **argv)
+{
+       int i;
+
+       fbs = 0;
+       edid = 0;
+       crtcs = 0;
+       modes = 0;
+       encoders = 0;
+       full_modes = 0;
+       full_props = 0;
+       connectors = 0;
+
+       module_name = argv[1];
+
+       for (i = 2; i < argc; i++) {
+               if (strcmp(argv[i], "-fb") == 0) {
+                       fbs = 1;
+               } else if (strcmp(argv[i], "-crtcs") == 0) {
+                       crtcs = 1;
+               } else if (strcmp(argv[i], "-cons") == 0) {
+                       connectors = 1;
+                       modes = 1;
+               } else if (strcmp(argv[i], "-modes") == 0) {
+                       connectors = 1;
+                       modes = 1;
+               } else if (strcmp(argv[i], "-full") == 0) {
+                       connectors = 1;
+                       modes = 1;
+                       full_modes = 1;
+               } else if (strcmp(argv[i], "-props") == 0) {
+                       connectors = 1;
+                       full_props = 1;
+               } else if (strcmp(argv[i], "-edids") == 0) {
+                       connectors = 1;
+                       edid = 1;
+               } else if (strcmp(argv[i], "-encoders") == 0) {
+                       encoders = 1;
+               } else if (strcmp(argv[i], "-v") == 0) {
+                       fbs = 1;
+                       edid = 1;
+                       crtcs = 1;
+                       modes = 1;
+                       encoders = 1;
+                       full_modes = 1;
+                       full_props = 1;
+                       connectors = 1;
+               }
+       }
+
+       if (argc == 2) {
+               fbs = 1;
+               edid = 1;
+               crtcs = 1;
+               modes = 1;
+               encoders = 1;
+               full_modes = 0;
+               full_props = 0;
+               connectors = 1;
+       }
+}
+
+int main(int argc, char **argv)
+{
+       int fd;
+       drmModeResPtr res;
+
+       if (argc == 1) {
+               printf("Please add modulename as first argument\n");
+               return 1;
+       }
+
+       args(argc, argv);
+
+       printf("Starting test\n");
+
+       fd = drmOpen(module_name, NULL);
+
+       if (fd < 0) {
+               printf("Failed to open the card fd (%d)\n",fd);
+               return 1;
+       }
+
+       res = drmModeGetResources(fd);
+       if (res == 0) {
+               printf("Failed to get resources from card\n");
+               drmClose(fd);
+               return 1;
+       }
+
+       printRes(fd, res);
+
+       drmModeFreeResources(res);
+
+       printf("Ok\n");
+
+       return 0;
+}
diff --git a/tests/modeprint/test b/tests/modeprint/test
new file mode 100644 (file)
index 0000000..bd1952c
--- /dev/null
@@ -0,0 +1 @@
+LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@
diff --git a/tests/modetest/Makefile b/tests/modetest/Makefile
new file mode 100644 (file)
index 0000000..8583ae8
--- /dev/null
@@ -0,0 +1,14 @@
+
+all: app
+
+#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \
+#        -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \
+
+app: modetest.c
+       gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../libdrm/intel -I../../shared-core -L../../libdrm/.libs -L../../libdrm/intel/.libs -ldrm -ldrm_intel modetest.c
+
+clean:
+       @rm -f app
+
+run: app
+       sudo ./test
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
new file mode 100644 (file)
index 0000000..e5a16e1
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * DRM based mode setting test program
+ * Copyright 2008 Tungsten Graphics
+ *   Jakob Bornecrantz <jakob@tungstengraphics.com>
+ * Copyright 2008 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/*
+ * This fairly simple test program dumps output in a similar format to the
+ * "xrandr" tool everyone knows & loves.  It's necessarily slightly different
+ * since the kernel separates outputs into encoder and connector structures,
+ * each with their own unique ID.  The program also allows test testing of the
+ * memory management and mode setting APIs by allowing the user to specify a
+ * connector and mode to use for mode setting.  If all works as expected, a
+ * blue background should be painted on the monitor attached to the specified
+ * connector after the selected mode is set.
+ *
+ * TODO: use cairo to write the mode info on the selected output once
+ *       the mode has been programmed, along with possible test patterns.
+ */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "intel_bufmgr.h"
+
+drmModeRes *resources;
+int fd, modes;
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct type_name {
+       int type;
+       char *name;
+};
+
+#define type_name_fn(res) \
+char * res##_str(int type) {                   \
+       int i;                                          \
+       for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
+               if (res##_names[i].type == type)        \
+                       return res##_names[i].name;     \
+       }                                               \
+       return "(invalid)";                             \
+}
+
+struct type_name encoder_type_names[] = {
+       { DRM_MODE_ENCODER_NONE, "none" },
+       { DRM_MODE_ENCODER_DAC, "DAC" },
+       { DRM_MODE_ENCODER_TMDS, "TMDS" },
+       { DRM_MODE_ENCODER_LVDS, "LVDS" },
+       { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
+};
+
+type_name_fn(encoder_type)
+
+struct type_name connector_status_names[] = {
+       { DRM_MODE_CONNECTED, "connected" },
+       { DRM_MODE_DISCONNECTED, "disconnected" },
+       { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
+};
+
+type_name_fn(connector_status)
+
+struct type_name connector_type_names[] = {
+       { DRM_MODE_CONNECTOR_Unknown, "unknown" },
+       { DRM_MODE_CONNECTOR_VGA, "VGA" },
+       { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
+       { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
+       { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
+       { DRM_MODE_CONNECTOR_Composite, "composite" },
+       { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
+       { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
+       { DRM_MODE_CONNECTOR_Component, "component" },
+       { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
+       { DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
+       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
+       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
+};
+
+type_name_fn(connector_type)
+
+void dump_encoders(void)
+{
+       drmModeEncoder *encoder;
+       int i;
+
+       printf("Encoders:\n");
+       printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
+       for (i = 0; i < resources->count_encoders; i++) {
+               encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+               if (!encoder) {
+                       fprintf(stderr, "could not get encoder %i: %s\n",
+                               resources->encoders[i], strerror(errno));
+                       continue;
+               }
+               printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
+                      encoder->encoder_id,
+                      encoder->crtc_id,
+                      encoder_type_str(encoder->encoder_type),
+                      encoder->possible_crtcs,
+                      encoder->possible_clones);
+               drmModeFreeEncoder(encoder);
+       }
+}
+
+void dump_connectors(void)
+{
+       drmModeConnector *connector;
+       int i, j;
+
+       printf("Connectors:\n");
+       printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
+       for (i = 0; i < resources->count_connectors; i++) {
+               connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+               if (!connector) {
+                       fprintf(stderr, "could not get connector %i: %s\n",
+                               resources->connectors[i], strerror(errno));
+                       continue;
+               }
+
+               printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
+                      connector->connector_id,
+                      connector->encoder_id,
+                      connector_status_str(connector->connection),
+                      connector_type_str(connector->connector_type),
+                      connector->mmWidth, connector->mmHeight,
+                      connector->count_modes);
+
+               if (!connector->count_modes)
+                       continue;
+
+               printf("  modes:\n");
+               printf("  name refresh (Hz) hdisp hss hse htot vdisp "
+                      "vss vse vtot)\n");
+               for (j = 0; j < connector->count_modes; j++) {
+                       struct drm_mode_modeinfo *mode;
+
+                       mode = &connector->modes[j];
+                       printf("  %s %.02f %d %d %d %d %d %d %d %d\n",
+                              mode->name,
+                              (float)mode->vrefresh / 1000,
+                              mode->hdisplay,
+                              mode->hsync_start,
+                              mode->hsync_end,
+                              mode->htotal,
+                              mode->vdisplay,
+                              mode->vsync_start,
+                              mode->vsync_end,
+                              mode->vtotal);
+               }
+               drmModeFreeConnector(connector);
+       }
+}
+
+void dump_crtcs(void)
+{
+       drmModeCrtc *crtc;
+       int i;
+
+       for (i = 0; i < resources->count_crtcs; i++) {
+               crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
+
+               if (!crtc) {
+                       fprintf(stderr, "could not get crtc %i: %s\n",
+                               resources->crtcs[i], strerror(errno));
+                       continue;
+               }
+               drmModeFreeCrtc(crtc);
+       }
+}
+
+void dump_framebuffers(void)
+{
+       drmModeFB *fb;
+       int i;
+
+       for (i = 0; i < resources->count_fbs; i++) {
+               fb = drmModeGetFB(fd, resources->fbs[i]);
+
+               if (!fb) {
+                       fprintf(stderr, "could not get fb %i: %s\n",
+                               resources->fbs[i], strerror(errno));
+                       continue;
+               }
+               drmModeFreeFB(fb);
+       }
+}
+
+/*
+ * Mode setting with the kernel interfaces is a bit of a chore.
+ * First you have to find the connector in question and make sure the
+ * requested mode is available.
+ * Then you need to find the encoder attached to that connector so you
+ * can bind it with a free crtc.
+ */
+void set_mode(int connector_id, char *mode_str)
+{
+       drmModeConnector *connector;
+       drmModeEncoder *encoder = NULL;
+       struct drm_mode_modeinfo *mode = NULL;
+       drm_intel_bufmgr *bufmgr;
+       drm_intel_bo *bo;
+       unsigned int fb_id, *fb_ptr;
+       int i, j, size, ret, width, height;
+
+       /* First, find the connector & mode */
+       for (i = 0; i < resources->count_connectors; i++) {
+               connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+               if (!connector) {
+                       fprintf(stderr, "could not get connector %i: %s\n",
+                               resources->connectors[i], strerror(errno));
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               if (!connector->count_modes) {
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               if (connector->connector_id != connector_id) {
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               for (j = 0; j < connector->count_modes; j++) {
+                       mode = &connector->modes[j];
+                       if (!strcmp(mode->name, mode_str))
+                               break;
+               }
+
+               /* Found it, break out */
+               if (mode)
+                       break;
+
+               drmModeFreeConnector(connector);
+       }
+
+       if (!mode) {
+               fprintf(stderr, "failed to find mode \"%s\"\n", mode_str);
+               return;
+       }
+
+       width = mode->hdisplay;
+       height = mode->vdisplay;
+
+       /* Now get the encoder */
+       for (i = 0; i < resources->count_encoders; i++) {
+               encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+               if (!encoder) {
+                       fprintf(stderr, "could not get encoder %i: %s\n",
+                               resources->encoders[i], strerror(errno));
+                       drmModeFreeEncoder(encoder);
+                       continue;
+               }
+
+               if (encoder->encoder_id  == connector->encoder_id)
+                       break;
+
+               drmModeFreeEncoder(encoder);
+       }
+
+       bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20);
+       if (!bufmgr) {
+               fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno));
+               return;
+       }
+
+       /* Mode size at 32 bpp */
+       size = width * height * 4;
+
+       bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096);
+       if (!bo) {
+               fprintf(stderr, "failed to alloc buffer: %s\n",
+                       strerror(errno));
+               return;
+       }
+
+       ret = drm_intel_bo_pin(bo, 4096);
+       if (ret) {
+               fprintf(stderr, "failed to pin buffer: %s\n", strerror(errno));
+               return;
+       }
+
+       ret = drm_intel_gem_bo_map_gtt(bo);
+       if (ret) {
+               fprintf(stderr, "failed to GTT map buffer: %s\n",
+                       strerror(errno));
+               return;
+       }
+
+       fb_ptr = bo->virtual;
+
+       /* paint the buffer blue */
+       for (i = 0; i < width * height; i++)
+               fb_ptr[i] = 0xff;
+
+       ret = drmModeAddFB(fd, width, height, 32, 32, width * 4, bo->handle,
+                          &fb_id);
+       if (ret) {
+               fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
+               return;
+       }
+
+       ret = drmModeSetCrtc(fd, encoder->crtc_id, fb_id, 0, 0,
+                            &connector->connector_id, 1, mode);
+       if (ret) {
+               fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
+               return;
+       }
+}
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "ecpmfs:";
+
+void usage(char *name)
+{
+       fprintf(stderr, "usage: %s [-ecpmf]\n", name);
+       fprintf(stderr, "\t-e\tlist encoders\n");
+       fprintf(stderr, "\t-c\tlist connectors\n");
+       fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
+       fprintf(stderr, "\t-m\tlist modes\n");
+       fprintf(stderr, "\t-f\tlist framebuffers\n");
+       fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
+       fprintf(stderr, "\n\tDefault is to dump all info.\n");
+       exit(0);
+}
+
+#define dump_resource(res) if (res) dump_##res()
+
+int main(int argc, char **argv)
+{
+       int c;
+       int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
+       char *modules[] = { "i915", "radeon" };
+       char *modeset = NULL, *mode, *connector;
+       int i, connector_id;
+
+       opterr = 0;
+       while ((c = getopt(argc, argv, optstr)) != -1) {
+               switch (c) {
+               case 'e':
+                       encoders = 1;
+                       break;
+               case 'c':
+                       connectors = 1;
+                       break;
+               case 'p':
+                       crtcs = 1;
+                       break;
+               case 'm':
+                       modes = 1;
+                       break;
+               case 'f':
+                       framebuffers = 1;
+                       break;
+               case 's':
+                       modeset = strdup(optarg);
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       if (argc == 1)
+               encoders = connectors = crtcs = modes = framebuffers = 1;
+
+       for (i = 0; i < ARRAY_SIZE(modules); i++) {
+               printf("trying to load module %s...", modules[i]);
+               fd = drmOpen(modules[i], NULL);
+               if (fd < 0) {
+                       printf("failed.\n");
+               } else {
+                       printf("success.\n");
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(modules)) {
+               fprintf(stderr, "failed to load any modules, aborting.\n");
+               return -1;
+       }
+
+       resources = drmModeGetResources(fd);
+       if (!resources) {
+               fprintf(stderr, "drmModeGetResources failed: %s\n",
+                       strerror(errno));
+               drmClose(fd);
+               return 1;
+       }
+
+       dump_resource(encoders);
+       dump_resource(connectors);
+       dump_resource(crtcs);
+       dump_resource(framebuffers);
+
+       if (modeset) {
+               connector = strtok(modeset, ":");
+               if (!connector)
+                       usage(argv[0]);
+               connector_id = atoi(connector);
+
+               mode = strtok(NULL, ":");
+               if (!mode)
+                       usage(argv[0]);
+               printf("setting connector %d to mode %s\n", connector_id,
+                      mode);
+               set_mode(connector_id, mode);
+               sleep(3);
+       }
+
+       sleep(3);
+
+       drmModeFreeResources(resources);
+
+       return 0;
+}
diff --git a/tests/modetest/test b/tests/modetest/test
new file mode 100644 (file)
index 0000000..5bb552e
--- /dev/null
@@ -0,0 +1,2 @@
+export LD_LIBRARY_PATH=../../libdrm/.libs:../../libdrm/intel/.libs
+LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@