diff options
author | Jesse Barnes | 2008-12-17 12:09:49 -0600 |
---|---|---|
committer | Jesse Barnes | 2008-12-17 12:11:37 -0600 |
commit | 731cd5526e5c732d51307b26e784f454a724a699 (patch) | |
tree | 215249e4aa86a3d8418b7f5cad95551d49ecce2d | |
parent | c86d431fe6174b1c2de531929213ea7dbd92326d (diff) | |
download | external-libdrm-731cd5526e5c732d51307b26e784f454a724a699.tar.gz external-libdrm-731cd5526e5c732d51307b26e784f454a724a699.tar.xz external-libdrm-731cd5526e5c732d51307b26e784f454a724a699.zip |
libdrm: add mode setting files
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.
-rw-r--r-- | libdrm/Makefile.am | 3 | ||||
-rw-r--r-- | libdrm/intel/intel_bufmgr.h | 5 | ||||
-rw-r--r-- | libdrm/intel/intel_bufmgr_gem.c | 1 | ||||
-rw-r--r-- | libdrm/xf86drm.c | 44 | ||||
-rw-r--r-- | libdrm/xf86drm.h | 6 | ||||
-rw-r--r-- | libdrm/xf86drmMode.c | 686 | ||||
-rw-r--r-- | libdrm/xf86drmMode.h | 258 | ||||
l--------- | linux-core/drm_mode.h | 1 | ||||
-rw-r--r-- | shared-core/Makefile.am | 1 | ||||
-rw-r--r-- | shared-core/drm.h | 27 | ||||
-rw-r--r-- | shared-core/drm_mode.h | 271 | ||||
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/dristat.c | 2 | ||||
-rw-r--r-- | tests/modeprint/Makefile | 14 | ||||
-rwxr-xr-x | tests/modeprint/app | bin | 0 -> 16233 bytes | |||
-rw-r--r-- | tests/modeprint/modeprint.c | 402 | ||||
-rw-r--r-- | tests/modeprint/test | 1 | ||||
-rw-r--r-- | tests/modetest/Makefile | 14 | ||||
-rw-r--r-- | tests/modetest/modetest.c | 449 | ||||
-rw-r--r-- | tests/modetest/test | 2 |
20 files changed, 2179 insertions, 12 deletions
diff --git a/libdrm/Makefile.am b/libdrm/Makefile.am index a5be36e0..eb63abe1 100644 --- a/libdrm/Makefile.am +++ b/libdrm/Makefile.am | |||
@@ -26,9 +26,10 @@ libdrm_la_LDFLAGS = -version-number 2:4:0 -no-undefined | |||
26 | 26 | ||
27 | AM_CFLAGS = -I$(top_srcdir)/shared-core | 27 | AM_CFLAGS = -I$(top_srcdir)/shared-core |
28 | libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \ | 28 | libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \ |
29 | xf86drmMode.c libdrm_lists.h | ||
29 | libdrm_lists.h | 30 | libdrm_lists.h |
30 | 31 | ||
31 | libdrmincludedir = ${includedir} | 32 | libdrmincludedir = ${includedir} |
32 | libdrminclude_HEADERS = xf86drm.h | 33 | libdrminclude_HEADERS = xf86drm.h xf86drmMode.h |
33 | 34 | ||
34 | EXTRA_DIST = ChangeLog TODO | 35 | EXTRA_DIST = ChangeLog TODO |
diff --git a/libdrm/intel/intel_bufmgr.h b/libdrm/intel/intel_bufmgr.h index f134f169..e8c2e063 100644 --- a/libdrm/intel/intel_bufmgr.h +++ b/libdrm/intel/intel_bufmgr.h | |||
@@ -66,6 +66,11 @@ struct _drm_intel_bo { | |||
66 | 66 | ||
67 | /** Buffer manager context associated with this buffer object */ | 67 | /** Buffer manager context associated with this buffer object */ |
68 | drm_intel_bufmgr *bufmgr; | 68 | drm_intel_bufmgr *bufmgr; |
69 | |||
70 | /** | ||
71 | * MM-specific handle for accessing object | ||
72 | */ | ||
73 | int handle; | ||
69 | }; | 74 | }; |
70 | 75 | ||
71 | drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, | 76 | drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, |
diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index e5a1375e..9605cc7c 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c | |||
@@ -351,6 +351,7 @@ drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name, | |||
351 | 351 | ||
352 | ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create); | 352 | ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create); |
353 | bo_gem->gem_handle = create.handle; | 353 | bo_gem->gem_handle = create.handle; |
354 | bo_gem->bo.handle = bo_gem->gem_handle; | ||
354 | if (ret != 0) { | 355 | if (ret != 0) { |
355 | free(bo_gem); | 356 | free(bo_gem); |
356 | return NULL; | 357 | return NULL; |
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index c36f1964..0b5d31fe 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c | |||
@@ -87,6 +87,9 @@ | |||
87 | 87 | ||
88 | #define DRM_MSG_VERBOSITY 3 | 88 | #define DRM_MSG_VERBOSITY 3 |
89 | 89 | ||
90 | #define DRM_NODE_CONTROL 0 | ||
91 | #define DRM_NODE_RENDER 1 | ||
92 | |||
90 | static drmServerInfoPtr drm_server_info; | 93 | static drmServerInfoPtr drm_server_info; |
91 | 94 | ||
92 | void drmSetServerInfo(drmServerInfoPtr info) | 95 | void drmSetServerInfo(drmServerInfoPtr info) |
@@ -174,7 +177,7 @@ static char *drmStrdup(const char *s) | |||
174 | /** | 177 | /** |
175 | * Call ioctl, restarting if it is interupted | 178 | * Call ioctl, restarting if it is interupted |
176 | */ | 179 | */ |
177 | static int | 180 | int |
178 | drmIoctl(int fd, unsigned long request, void *arg) | 181 | drmIoctl(int fd, unsigned long request, void *arg) |
179 | { | 182 | { |
180 | int ret; | 183 | int ret; |
@@ -277,7 +280,7 @@ static int drmMatchBusID(const char *id1, const char *id2) | |||
277 | * special file node with the major and minor numbers specified by \p dev and | 280 | * special file node with the major and minor numbers specified by \p dev and |
278 | * parent directory if necessary and was called by root. | 281 | * parent directory if necessary and was called by root. |
279 | */ | 282 | */ |
280 | static int drmOpenDevice(long dev, int minor) | 283 | static int drmOpenDevice(long dev, int minor, int type) |
281 | { | 284 | { |
282 | stat_t st; | 285 | stat_t st; |
283 | char buf[64]; | 286 | char buf[64]; |
@@ -287,7 +290,7 @@ static int drmOpenDevice(long dev, int minor) | |||
287 | uid_t user = DRM_DEV_UID; | 290 | uid_t user = DRM_DEV_UID; |
288 | gid_t group = DRM_DEV_GID, serv_group; | 291 | gid_t group = DRM_DEV_GID, serv_group; |
289 | 292 | ||
290 | sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); | 293 | sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor); |
291 | drmMsg("drmOpenDevice: node name is %s\n", buf); | 294 | drmMsg("drmOpenDevice: node name is %s\n", buf); |
292 | 295 | ||
293 | if (drm_server_info) { | 296 | if (drm_server_info) { |
@@ -386,15 +389,15 @@ wait_for_udev: | |||
386 | * Calls drmOpenDevice() if \p create is set, otherwise assembles the device | 389 | * Calls drmOpenDevice() if \p create is set, otherwise assembles the device |
387 | * name from \p minor and opens it. | 390 | * name from \p minor and opens it. |
388 | */ | 391 | */ |
389 | static int drmOpenMinor(int minor, int create) | 392 | static int drmOpenMinor(int minor, int create, int type) |
390 | { | 393 | { |
391 | int fd; | 394 | int fd; |
392 | char buf[64]; | 395 | char buf[64]; |
393 | 396 | ||
394 | if (create) | 397 | if (create) |
395 | return drmOpenDevice(makedev(DRM_MAJOR, minor), minor); | 398 | return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type); |
396 | 399 | ||
397 | sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); | 400 | sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor); |
398 | if ((fd = open(buf, O_RDWR, 0)) >= 0) | 401 | if ((fd = open(buf, O_RDWR, 0)) >= 0) |
399 | return fd; | 402 | return fd; |
400 | return -errno; | 403 | return -errno; |
@@ -417,7 +420,7 @@ int drmAvailable(void) | |||
417 | int retval = 0; | 420 | int retval = 0; |
418 | int fd; | 421 | int fd; |
419 | 422 | ||
420 | if ((fd = drmOpenMinor(0, 1)) < 0) { | 423 | if ((fd = drmOpenMinor(0, 1, DRM_NODE_RENDER)) < 0) { |
421 | #ifdef __linux__ | 424 | #ifdef __linux__ |
422 | /* Try proc for backward Linux compatibility */ | 425 | /* Try proc for backward Linux compatibility */ |
423 | if (!access("/proc/dri/0", R_OK)) | 426 | if (!access("/proc/dri/0", R_OK)) |
@@ -458,7 +461,7 @@ static int drmOpenByBusid(const char *busid) | |||
458 | 461 | ||
459 | drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); | 462 | drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); |
460 | for (i = 0; i < DRM_MAX_MINOR; i++) { | 463 | for (i = 0; i < DRM_MAX_MINOR; i++) { |
461 | fd = drmOpenMinor(i, 1); | 464 | fd = drmOpenMinor(i, 1, DRM_NODE_RENDER); |
462 | drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); | 465 | drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); |
463 | if (fd >= 0) { | 466 | if (fd >= 0) { |
464 | sv.drm_di_major = 1; | 467 | sv.drm_di_major = 1; |
@@ -520,7 +523,7 @@ static int drmOpenByName(const char *name) | |||
520 | * already in use. If it's in use it will have a busid assigned already. | 523 | * already in use. If it's in use it will have a busid assigned already. |
521 | */ | 524 | */ |
522 | for (i = 0; i < DRM_MAX_MINOR; i++) { | 525 | for (i = 0; i < DRM_MAX_MINOR; i++) { |
523 | if ((fd = drmOpenMinor(i, 1)) >= 0) { | 526 | if ((fd = drmOpenMinor(i, 1, DRM_NODE_RENDER)) >= 0) { |
524 | if ((version = drmGetVersion(fd))) { | 527 | if ((version = drmGetVersion(fd))) { |
525 | if (!strcmp(version->name, name)) { | 528 | if (!strcmp(version->name, name)) { |
526 | drmFreeVersion(version); | 529 | drmFreeVersion(version); |
@@ -564,7 +567,7 @@ static int drmOpenByName(const char *name) | |||
564 | if (*pt) { /* Found busid */ | 567 | if (*pt) { /* Found busid */ |
565 | return drmOpenByBusid(++pt); | 568 | return drmOpenByBusid(++pt); |
566 | } else { /* No busid */ | 569 | } else { /* No busid */ |
567 | return drmOpenDevice(strtol(devstring, NULL, 0),i); | 570 | return drmOpenDevice(strtol(devstring, NULL, 0),i, DRM_NODE_RENDER); |
568 | } | 571 | } |
569 | } | 572 | } |
570 | } | 573 | } |
@@ -614,6 +617,10 @@ int drmOpen(const char *name, const char *busid) | |||
614 | return -1; | 617 | return -1; |
615 | } | 618 | } |
616 | 619 | ||
620 | int drmOpenControl(int minor) | ||
621 | { | ||
622 | return drmOpenMinor(minor, 0, DRM_NODE_CONTROL); | ||
623 | } | ||
617 | 624 | ||
618 | /** | 625 | /** |
619 | * Free the version information returned by drmGetVersion(). | 626 | * Free the version information returned by drmGetVersion(). |
@@ -2434,3 +2441,20 @@ void drmCloseOnce(int fd) | |||
2434 | } | 2441 | } |
2435 | } | 2442 | } |
2436 | } | 2443 | } |
2444 | |||
2445 | int drmSetMaster(int fd) | ||
2446 | { | ||
2447 | int ret; | ||
2448 | |||
2449 | fprintf(stderr,"Setting master \n"); | ||
2450 | ret = ioctl(fd, DRM_IOCTL_SET_MASTER, 0); | ||
2451 | return ret; | ||
2452 | } | ||
2453 | |||
2454 | int drmDropMaster(int fd) | ||
2455 | { | ||
2456 | int ret; | ||
2457 | fprintf(stderr,"Dropping master \n"); | ||
2458 | ret = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0); | ||
2459 | return ret; | ||
2460 | } | ||
diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h index f4fa71b0..f9dd1bfc 100644 --- a/libdrm/xf86drm.h +++ b/libdrm/xf86drm.h | |||
@@ -49,6 +49,7 @@ | |||
49 | 49 | ||
50 | #define DRM_DIR_NAME "/dev/dri" | 50 | #define DRM_DIR_NAME "/dev/dri" |
51 | #define DRM_DEV_NAME "%s/card%d" | 51 | #define DRM_DEV_NAME "%s/card%d" |
52 | #define DRM_CONTROL_DEV_NAME "%s/controlD%d" | ||
52 | #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ | 53 | #define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ |
53 | 54 | ||
54 | #define DRM_ERR_NO_DEVICE (-1001) | 55 | #define DRM_ERR_NO_DEVICE (-1001) |
@@ -74,6 +75,7 @@ typedef struct drmHashEntry { | |||
74 | void *tagTable; | 75 | void *tagTable; |
75 | } drmHashEntry; | 76 | } drmHashEntry; |
76 | 77 | ||
78 | extern int drmIoctl(int fd, unsigned long request, void *arg); | ||
77 | extern void *drmGetHashTable(void); | 79 | extern void *drmGetHashTable(void); |
78 | extern drmHashEntry *drmGetEntry(int fd); | 80 | extern drmHashEntry *drmGetEntry(int fd); |
79 | 81 | ||
@@ -508,6 +510,7 @@ do { register unsigned int __old __asm("o0"); \ | |||
508 | /* General user-level programmer's API: unprivileged */ | 510 | /* General user-level programmer's API: unprivileged */ |
509 | extern int drmAvailable(void); | 511 | extern int drmAvailable(void); |
510 | extern int drmOpen(const char *name, const char *busid); | 512 | extern int drmOpen(const char *name, const char *busid); |
513 | extern int drmOpenControl(int minor); | ||
511 | extern int drmClose(int fd); | 514 | extern int drmClose(int fd); |
512 | extern drmVersionPtr drmGetVersion(int fd); | 515 | extern drmVersionPtr drmGetVersion(int fd); |
513 | extern drmVersionPtr drmGetLibVersion(int fd); | 516 | extern drmVersionPtr drmGetLibVersion(int fd); |
@@ -659,4 +662,7 @@ extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened); | |||
659 | extern void drmCloseOnce(int fd); | 662 | extern void drmCloseOnce(int fd); |
660 | extern void drmMsg(const char *format, ...); | 663 | extern void drmMsg(const char *format, ...); |
661 | 664 | ||
665 | extern int drmSetMaster(int fd); | ||
666 | extern int drmDropMaster(int fd); | ||
667 | |||
662 | #endif | 668 | #endif |
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c new file mode 100644 index 00000000..f481428e --- /dev/null +++ b/libdrm/xf86drmMode.c | |||
@@ -0,0 +1,686 @@ | |||
1 | /* | ||
2 | * \file xf86drmMode.c | ||
3 | * Header for DRM modesetting interface. | ||
4 | * | ||
5 | * \author Jakob Bornecrantz <wallbraker@gmail.com> | ||
6 | * | ||
7 | * \par Acknowledgements: | ||
8 | * Feb 2007, Dave Airlie <airlied@linux.ie> | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. | ||
13 | * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie> | ||
14 | * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> | ||
15 | * | ||
16 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
17 | * copy of this software and associated documentation files (the "Software"), | ||
18 | * to deal in the Software without restriction, including without limitation | ||
19 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
20 | * and/or sell copies of the Software, and to permit persons to whom the | ||
21 | * Software is furnished to do so, subject to the following conditions: | ||
22 | * | ||
23 | * The above copyright notice and this permission notice shall be included in | ||
24 | * all copies or substantial portions of the Software. | ||
25 | * | ||
26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
27 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
28 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
29 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
30 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
31 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
32 | * IN THE SOFTWARE. | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | /* | ||
37 | * TODO the types we are after are defined in diffrent headers on diffrent | ||
38 | * platforms find which headers to include to get uint32_t | ||
39 | */ | ||
40 | #include <stdint.h> | ||
41 | #include <sys/ioctl.h> | ||
42 | #include <stdio.h> | ||
43 | |||
44 | #include "xf86drmMode.h" | ||
45 | #include "xf86drm.h" | ||
46 | #include <drm.h> | ||
47 | #include <string.h> | ||
48 | #include <dirent.h> | ||
49 | #include <errno.h> | ||
50 | |||
51 | #define U642VOID(x) ((void *)(unsigned long)(x)) | ||
52 | #define VOID2U64(x) ((uint64_t)(unsigned long)(x)) | ||
53 | |||
54 | /* | ||
55 | * Util functions | ||
56 | */ | ||
57 | |||
58 | void* drmAllocCpy(void *array, int count, int entry_size) | ||
59 | { | ||
60 | char *r; | ||
61 | int i; | ||
62 | |||
63 | if (!count || !array || !entry_size) | ||
64 | return 0; | ||
65 | |||
66 | if (!(r = drmMalloc(count*entry_size))) | ||
67 | return 0; | ||
68 | |||
69 | for (i = 0; i < count; i++) | ||
70 | memcpy(r+(entry_size*i), array+(entry_size*i), entry_size); | ||
71 | |||
72 | return r; | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * A couple of free functions. | ||
77 | */ | ||
78 | |||
79 | void drmModeFreeModeInfo(struct drm_mode_modeinfo *ptr) | ||
80 | { | ||
81 | if (!ptr) | ||
82 | return; | ||
83 | |||
84 | drmFree(ptr); | ||
85 | } | ||
86 | |||
87 | void drmModeFreeResources(drmModeResPtr ptr) | ||
88 | { | ||
89 | if (!ptr) | ||
90 | return; | ||
91 | |||
92 | drmFree(ptr); | ||
93 | |||
94 | } | ||
95 | |||
96 | void drmModeFreeFB(drmModeFBPtr ptr) | ||
97 | { | ||
98 | if (!ptr) | ||
99 | return; | ||
100 | |||
101 | /* we might add more frees later. */ | ||
102 | drmFree(ptr); | ||
103 | } | ||
104 | |||
105 | void drmModeFreeCrtc(drmModeCrtcPtr ptr) | ||
106 | { | ||
107 | if (!ptr) | ||
108 | return; | ||
109 | |||
110 | drmFree(ptr); | ||
111 | |||
112 | } | ||
113 | |||
114 | void drmModeFreeConnector(drmModeConnectorPtr ptr) | ||
115 | { | ||
116 | if (!ptr) | ||
117 | return; | ||
118 | |||
119 | drmFree(ptr->modes); | ||
120 | drmFree(ptr); | ||
121 | |||
122 | } | ||
123 | |||
124 | void drmModeFreeEncoder(drmModeEncoderPtr ptr) | ||
125 | { | ||
126 | drmFree(ptr); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * ModeSetting functions. | ||
131 | */ | ||
132 | |||
133 | drmModeResPtr drmModeGetResources(int fd) | ||
134 | { | ||
135 | struct drm_mode_card_res res; | ||
136 | drmModeResPtr r = 0; | ||
137 | |||
138 | memset(&res, 0, sizeof(struct drm_mode_card_res)); | ||
139 | |||
140 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) | ||
141 | return 0; | ||
142 | |||
143 | if (res.count_fbs) | ||
144 | res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t))); | ||
145 | if (res.count_crtcs) | ||
146 | res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t))); | ||
147 | if (res.count_connectors) | ||
148 | res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t))); | ||
149 | if (res.count_encoders) | ||
150 | res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t))); | ||
151 | |||
152 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) { | ||
153 | r = NULL; | ||
154 | goto err_allocs; | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * return | ||
159 | */ | ||
160 | |||
161 | |||
162 | if (!(r = drmMalloc(sizeof(*r)))) | ||
163 | return 0; | ||
164 | |||
165 | r->min_width = res.min_width; | ||
166 | r->max_width = res.max_width; | ||
167 | r->min_height = res.min_height; | ||
168 | r->max_height = res.max_height; | ||
169 | r->count_fbs = res.count_fbs; | ||
170 | r->count_crtcs = res.count_crtcs; | ||
171 | r->count_connectors = res.count_connectors; | ||
172 | r->count_encoders = res.count_encoders; | ||
173 | /* TODO we realy should test if these allocs fails. */ | ||
174 | r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t)); | ||
175 | r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t)); | ||
176 | r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t)); | ||
177 | r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t)); | ||
178 | |||
179 | err_allocs: | ||
180 | drmFree(U642VOID(res.fb_id_ptr)); | ||
181 | drmFree(U642VOID(res.crtc_id_ptr)); | ||
182 | drmFree(U642VOID(res.connector_id_ptr)); | ||
183 | drmFree(U642VOID(res.encoder_id_ptr)); | ||
184 | |||
185 | return r; | ||
186 | } | ||
187 | |||
188 | int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, | ||
189 | uint8_t bpp, uint32_t pitch, uint32_t bo_handle, | ||
190 | uint32_t *buf_id) | ||
191 | { | ||
192 | struct drm_mode_fb_cmd f; | ||
193 | int ret; | ||
194 | |||
195 | f.width = width; | ||
196 | f.height = height; | ||
197 | f.pitch = pitch; | ||
198 | f.bpp = bpp; | ||
199 | f.depth = depth; | ||
200 | f.handle = bo_handle; | ||
201 | |||
202 | if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &f))) | ||
203 | return ret; | ||
204 | |||
205 | *buf_id = f.fb_id; | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | int drmModeRmFB(int fd, uint32_t bufferId) | ||
210 | { | ||
211 | return drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId); | ||
212 | |||
213 | |||
214 | } | ||
215 | |||
216 | drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) | ||
217 | { | ||
218 | struct drm_mode_fb_cmd info; | ||
219 | drmModeFBPtr r; | ||
220 | |||
221 | info.fb_id = buf; | ||
222 | |||
223 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info)) | ||
224 | return NULL; | ||
225 | |||
226 | if (!(r = drmMalloc(sizeof(*r)))) | ||
227 | return NULL; | ||
228 | |||
229 | r->fb_id = info.fb_id; | ||
230 | r->width = info.width; | ||
231 | r->height = info.height; | ||
232 | r->pitch = info.pitch; | ||
233 | r->bpp = info.bpp; | ||
234 | r->handle = info.handle; | ||
235 | r->depth = info.depth; | ||
236 | |||
237 | return r; | ||
238 | } | ||
239 | |||
240 | |||
241 | /* | ||
242 | * Crtc functions | ||
243 | */ | ||
244 | |||
245 | drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) | ||
246 | { | ||
247 | struct drm_mode_crtc crtc; | ||
248 | drmModeCrtcPtr r; | ||
249 | |||
250 | crtc.crtc_id = crtcId; | ||
251 | |||
252 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc)) | ||
253 | return 0; | ||
254 | |||
255 | /* | ||
256 | * return | ||
257 | */ | ||
258 | |||
259 | if (!(r = drmMalloc(sizeof(*r)))) | ||
260 | return 0; | ||
261 | |||
262 | r->crtc_id = crtc.crtc_id; | ||
263 | r->x = crtc.x; | ||
264 | r->y = crtc.y; | ||
265 | r->mode_valid = crtc.mode_valid; | ||
266 | if (r->mode_valid) | ||
267 | memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo)); | ||
268 | r->buffer_id = crtc.fb_id; | ||
269 | r->gamma_size = crtc.gamma_size; | ||
270 | return r; | ||
271 | } | ||
272 | |||
273 | |||
274 | int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, | ||
275 | uint32_t x, uint32_t y, uint32_t *connectors, int count, | ||
276 | struct drm_mode_modeinfo *mode) | ||
277 | { | ||
278 | struct drm_mode_crtc crtc; | ||
279 | |||
280 | crtc.x = x; | ||
281 | crtc.y = y; | ||
282 | crtc.crtc_id = crtcId; | ||
283 | crtc.fb_id = bufferId; | ||
284 | crtc.set_connectors_ptr = VOID2U64(connectors); | ||
285 | crtc.count_connectors = count; | ||
286 | if (mode) { | ||
287 | memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo)); | ||
288 | crtc.mode_valid = 1; | ||
289 | } else | ||
290 | crtc.mode_valid = 0; | ||
291 | |||
292 | return drmIoctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Cursor manipulation | ||
297 | */ | ||
298 | |||
299 | int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height) | ||
300 | { | ||
301 | struct drm_mode_cursor arg; | ||
302 | |||
303 | arg.flags = DRM_MODE_CURSOR_BO; | ||
304 | arg.crtc_id = crtcId; | ||
305 | arg.width = width; | ||
306 | arg.height = height; | ||
307 | arg.handle = bo_handle; | ||
308 | |||
309 | return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg); | ||
310 | } | ||
311 | |||
312 | int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) | ||
313 | { | ||
314 | struct drm_mode_cursor arg; | ||
315 | |||
316 | arg.flags = DRM_MODE_CURSOR_MOVE; | ||
317 | arg.crtc_id = crtcId; | ||
318 | arg.x = x; | ||
319 | arg.y = y; | ||
320 | |||
321 | return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg); | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | * Encoder get | ||
326 | */ | ||
327 | drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) | ||
328 | { | ||
329 | struct drm_mode_get_encoder enc; | ||
330 | drmModeEncoderPtr r = NULL; | ||
331 | |||
332 | enc.encoder_id = encoder_id; | ||
333 | enc.encoder_type = 0; | ||
334 | enc.possible_crtcs = 0; | ||
335 | enc.possible_clones = 0; | ||
336 | |||
337 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc)) | ||
338 | return 0; | ||
339 | |||
340 | if (!(r = drmMalloc(sizeof(*r)))) | ||
341 | return 0; | ||
342 | |||
343 | r->encoder_id = enc.encoder_id; | ||
344 | r->crtc_id = enc.crtc_id; | ||
345 | r->encoder_type = enc.encoder_type; | ||
346 | r->possible_crtcs = enc.possible_crtcs; | ||
347 | r->possible_clones = enc.possible_clones; | ||
348 | |||
349 | return r; | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * Connector manipulation | ||
354 | */ | ||
355 | |||
356 | drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) | ||
357 | { | ||
358 | struct drm_mode_get_connector conn; | ||
359 | drmModeConnectorPtr r = NULL; | ||
360 | |||
361 | conn.connector_id = connector_id; | ||
362 | conn.connector_type_id = 0; | ||
363 | conn.connector_type = 0; | ||
364 | conn.count_modes = 0; | ||
365 | conn.modes_ptr = 0; | ||
366 | conn.count_props = 0; | ||
367 | conn.props_ptr = 0; | ||
368 | conn.prop_values_ptr = 0; | ||
369 | conn.count_encoders = 0; | ||
370 | conn.encoders_ptr = 0; | ||
371 | |||
372 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) | ||
373 | return 0; | ||
374 | |||
375 | if (conn.count_props) { | ||
376 | conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t))); | ||
377 | conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t))); | ||
378 | } | ||
379 | |||
380 | if (conn.count_modes) | ||
381 | conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); | ||
382 | |||
383 | if (conn.count_encoders) | ||
384 | conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t))); | ||
385 | |||
386 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) | ||
387 | goto err_allocs; | ||
388 | |||
389 | if(!(r = drmMalloc(sizeof(*r)))) { | ||
390 | goto err_allocs; | ||
391 | } | ||
392 | |||
393 | r->connector_id = conn.connector_id; | ||
394 | r->encoder_id = conn.encoder_id; | ||
395 | r->connection = conn.connection; | ||
396 | r->mmWidth = conn.mm_width; | ||
397 | r->mmHeight = conn.mm_height; | ||
398 | r->subpixel = conn.subpixel; | ||
399 | r->count_modes = conn.count_modes; | ||
400 | /* TODO we should test if these alloc & cpy fails. */ | ||
401 | r->count_props = conn.count_props; | ||
402 | r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t)); | ||
403 | r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t)); | ||
404 | r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo)); | ||
405 | r->count_encoders = conn.count_encoders; | ||
406 | r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t)); | ||
407 | r->connector_type = conn.connector_type; | ||
408 | r->connector_type_id = conn.connector_type_id; | ||
409 | |||
410 | if (!r->props || !r->prop_values || !r->modes || !r->encoders) | ||
411 | goto err_allocs; | ||
412 | |||
413 | err_allocs: | ||
414 | drmFree(U642VOID(conn.prop_values_ptr)); | ||
415 | drmFree(U642VOID(conn.props_ptr)); | ||
416 | drmFree(U642VOID(conn.modes_ptr)); | ||
417 | drmFree(U642VOID(conn.encoders_ptr)); | ||
418 | |||
419 | return r; | ||
420 | } | ||
421 | |||
422 | int drmModeAttachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info) | ||
423 | { | ||
424 | struct drm_mode_mode_cmd res; | ||
425 | |||
426 | memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); | ||
427 | res.connector_id = connector_id; | ||
428 | |||
429 | return drmIoctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); | ||
430 | } | ||
431 | |||
432 | int drmModeDetachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info) | ||
433 | { | ||
434 | struct drm_mode_mode_cmd res; | ||
435 | |||
436 | memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); | ||
437 | res.connector_id = connector_id; | ||
438 | |||
439 | return drmIoctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res); | ||
440 | } | ||
441 | |||
442 | |||
443 | drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) | ||
444 | { | ||
445 | struct drm_mode_get_property prop; | ||
446 | drmModePropertyPtr r; | ||
447 | |||
448 | prop.prop_id = property_id; | ||
449 | prop.count_enum_blobs = 0; | ||
450 | prop.count_values = 0; | ||
451 | prop.flags = 0; | ||
452 | prop.enum_blob_ptr = 0; | ||
453 | prop.values_ptr = 0; | ||
454 | |||
455 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) | ||
456 | return 0; | ||
457 | |||
458 | if (prop.count_values) | ||
459 | prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t))); | ||
460 | |||
461 | if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM)) | ||
462 | prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum))); | ||
463 | |||
464 | if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) { | ||
465 | prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); | ||
466 | prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); | ||
467 | } | ||
468 | |||
469 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) { | ||
470 | r = NULL; | ||
471 | goto err_allocs; | ||
472 | } | ||
473 | |||
474 | if (!(r = drmMalloc(sizeof(*r)))) | ||
475 | return NULL; | ||
476 | |||
477 | r->prop_id = prop.prop_id; | ||
478 | r->count_values = prop.count_values; | ||
479 | |||
480 | r->flags = prop.flags; | ||
481 | if (prop.count_values) | ||
482 | r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t)); | ||
483 | if (prop.flags & DRM_MODE_PROP_ENUM) { | ||
484 | r->count_enums = prop.count_enum_blobs; | ||
485 | r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); | ||
486 | } else if (prop.flags & DRM_MODE_PROP_BLOB) { | ||
487 | r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t)); | ||
488 | r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t)); | ||
489 | r->count_blobs = prop.count_enum_blobs; | ||
490 | } | ||
491 | strncpy(r->name, prop.name, DRM_PROP_NAME_LEN); | ||
492 | r->name[DRM_PROP_NAME_LEN-1] = 0; | ||
493 | |||
494 | err_allocs: | ||
495 | drmFree(U642VOID(prop.values_ptr)); | ||
496 | drmFree(U642VOID(prop.enum_blob_ptr)); | ||
497 | |||
498 | return r; | ||
499 | } | ||
500 | |||
501 | void drmModeFreeProperty(drmModePropertyPtr ptr) | ||
502 | { | ||
503 | if (!ptr) | ||
504 | return; | ||
505 | |||
506 | drmFree(ptr->values); | ||
507 | drmFree(ptr->enums); | ||
508 | drmFree(ptr); | ||
509 | } | ||
510 | |||
511 | drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id) | ||
512 | { | ||
513 | struct drm_mode_get_blob blob; | ||
514 | drmModePropertyBlobPtr r; | ||
515 | |||
516 | blob.length = 0; | ||
517 | blob.data = 0; | ||
518 | blob.blob_id = blob_id; | ||
519 | |||
520 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) | ||
521 | return NULL; | ||
522 | |||
523 | if (blob.length) | ||
524 | blob.data = VOID2U64(drmMalloc(blob.length)); | ||
525 | |||
526 | if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) { | ||
527 | r = NULL; | ||
528 | goto err_allocs; | ||
529 | } | ||
530 | |||
531 | if (!(r = drmMalloc(sizeof(*r)))) | ||
532 | return NULL; | ||
533 | |||
534 | r->id = blob.blob_id; | ||
535 | r->length = blob.length; | ||
536 | r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length); | ||
537 | |||
538 | err_allocs: | ||
539 | drmFree(U642VOID(blob.data)); | ||
540 | return r; | ||
541 | } | ||
542 | |||
543 | void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) | ||
544 | { | ||
545 | if (!ptr) | ||
546 | return; | ||
547 | |||
548 | drmFree(ptr->data); | ||
549 | drmFree(ptr); | ||
550 | } | ||
551 | |||
552 | int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, | ||
553 | uint64_t value) | ||
554 | { | ||
555 | struct drm_mode_connector_set_property osp; | ||
556 | int ret; | ||
557 | |||
558 | osp.connector_id = connector_id; | ||
559 | osp.prop_id = property_id; | ||
560 | osp.value = value; | ||
561 | |||
562 | if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp))) | ||
563 | return ret; | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | /* | ||
569 | * checks if a modesetting capable driver has attached to the pci id | ||
570 | * returns 0 if modesetting supported. | ||
571 | * -EINVAL or invalid bus id | ||
572 | * -ENOSYS if no modesetting support | ||
573 | */ | ||
574 | int drmCheckModesettingSupported(const char *busid) | ||
575 | { | ||
576 | #ifdef __linux__ | ||
577 | char pci_dev_dir[1024]; | ||
578 | int domain, bus, dev, func; | ||
579 | DIR *sysdir; | ||
580 | struct dirent *dent; | ||
581 | int found = 0, ret; | ||
582 | |||
583 | ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); | ||
584 | if (ret != 4) | ||
585 | return -EINVAL; | ||
586 | |||
587 | sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm", | ||
588 | domain, bus, dev, func); | ||
589 | |||
590 | sysdir = opendir(pci_dev_dir); | ||
591 | if (sysdir) { | ||
592 | dent = readdir(sysdir); | ||
593 | while (dent) { | ||
594 | if (!strncmp(dent->d_name, "controlD", 8)) { | ||
595 | found = 1; | ||
596 | break; | ||
597 | } | ||
598 | |||
599 | dent = readdir(sysdir); | ||
600 | } | ||
601 | closedir(sysdir); | ||
602 | if (found) | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/", | ||
607 | domain, bus, dev, func); | ||
608 | |||
609 | sysdir = opendir(pci_dev_dir); | ||
610 | if (!sysdir) | ||
611 | return -EINVAL; | ||
612 | |||
613 | dent = readdir(sysdir); | ||
614 | while (dent) { | ||
615 | if (!strncmp(dent->d_name, "drm:controlD", 12)) { | ||
616 | found = 1; | ||
617 | break; | ||
618 | } | ||
619 | |||
620 | dent = readdir(sysdir); | ||
621 | } | ||
622 | |||
623 | closedir(sysdir); | ||
624 | if (found) | ||
625 | return 0; | ||
626 | #endif | ||
627 | return -ENOSYS; | ||
628 | |||
629 | } | ||
630 | |||
631 | int drmModeReplaceFB(int fd, uint32_t buffer_id, | ||
632 | uint32_t width, uint32_t height, uint8_t depth, | ||
633 | uint8_t bpp, uint32_t pitch, uint32_t bo_handle) | ||
634 | { | ||
635 | struct drm_mode_fb_cmd f; | ||
636 | int ret; | ||
637 | |||
638 | f.width = width; | ||
639 | f.height = height; | ||
640 | f.pitch = pitch; | ||
641 | f.bpp = bpp; | ||
642 | f.depth = depth; | ||
643 | f.handle = bo_handle; | ||
644 | f.fb_id = buffer_id; | ||
645 | |||
646 | if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_REPLACEFB, &f))) | ||
647 | return ret; | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, | ||
653 | uint16_t *red, uint16_t *green, uint16_t *blue) | ||
654 | { | ||
655 | int ret; | ||
656 | struct drm_mode_crtc_lut l; | ||
657 | |||
658 | l.crtc_id = crtc_id; | ||
659 | l.gamma_size = size; | ||
660 | l.red = VOID2U64(red); | ||
661 | l.green = VOID2U64(green); | ||
662 | l.blue = VOID2U64(blue); | ||
663 | |||
664 | if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l))) | ||
665 | return ret; | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, | ||
671 | uint16_t *red, uint16_t *green, uint16_t *blue) | ||
672 | { | ||
673 | int ret; | ||
674 | struct drm_mode_crtc_lut l; | ||
675 | |||
676 | l.crtc_id = crtc_id; | ||
677 | l.gamma_size = size; | ||
678 | l.red = VOID2U64(red); | ||
679 | l.green = VOID2U64(green); | ||
680 | l.blue = VOID2U64(blue); | ||
681 | |||
682 | if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l))) | ||
683 | return ret; | ||
684 | |||
685 | return 0; | ||
686 | } | ||
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h new file mode 100644 index 00000000..965b7be9 --- /dev/null +++ b/libdrm/xf86drmMode.h | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * \file xf86drmMode.h | ||
3 | * Header for DRM modesetting interface. | ||
4 | * | ||
5 | * \author Jakob Bornecrantz <wallbraker@gmail.com> | ||
6 | * | ||
7 | * \par Acknowledgements: | ||
8 | * Feb 2007, Dave Airlie <airlied@linux.ie> | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. | ||
13 | * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie> | ||
14 | * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> | ||
15 | * | ||
16 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
17 | * copy of this software and associated documentation files (the "Software"), | ||
18 | * to deal in the Software without restriction, including without limitation | ||
19 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
20 | * and/or sell copies of the Software, and to permit persons to whom the | ||
21 | * Software is furnished to do so, subject to the following conditions: | ||
22 | * | ||
23 | * The above copyright notice and this permission notice shall be included in | ||
24 | * all copies or substantial portions of the Software. | ||
25 | * | ||
26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
27 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
28 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
29 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
30 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
31 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
32 | * IN THE SOFTWARE. | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | #include <drm.h> | ||
37 | |||
38 | /* | ||
39 | * This is the interface for modesetting for drm. | ||
40 | * | ||
41 | * In order to use this interface you must include either <stdint.h> or another | ||
42 | * header defining uint32_t, int32_t and uint16_t. | ||
43 | * | ||
44 | * It aims to provide a randr1.2 compatible interface for modesettings in the | ||
45 | * kernel, the interface is also ment to be used by libraries like EGL. | ||
46 | * | ||
47 | * More information can be found in randrproto.txt which can be found here: | ||
48 | * http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git | ||
49 | * | ||
50 | * There are some major diffrences to be noted. Unlike the randr1.2 proto you | ||
51 | * need to create the memory object of the framebuffer yourself with the ttm | ||
52 | * buffer object interface. This object needs to be pinned. | ||
53 | */ | ||
54 | |||
55 | typedef struct _drmModeRes { | ||
56 | |||
57 | int count_fbs; | ||
58 | uint32_t *fbs; | ||
59 | |||
60 | int count_crtcs; | ||
61 | uint32_t *crtcs; | ||
62 | |||
63 | int count_connectors; | ||
64 | uint32_t *connectors; | ||
65 | |||
66 | int count_encoders; | ||
67 | uint32_t *encoders; | ||
68 | |||
69 | uint32_t min_width, max_width; | ||
70 | uint32_t min_height, max_height; | ||
71 | } drmModeRes, *drmModeResPtr; | ||
72 | |||
73 | typedef struct drm_mode_fb_cmd drmModeFB, *drmModeFBPtr; | ||
74 | |||
75 | typedef struct _drmModePropertyBlob { | ||
76 | uint32_t id; | ||
77 | uint32_t length; | ||
78 | void *data; | ||
79 | } drmModePropertyBlobRes, *drmModePropertyBlobPtr; | ||
80 | |||
81 | typedef struct _drmModeProperty { | ||
82 | uint32_t prop_id; | ||
83 | uint32_t flags; | ||
84 | char name[DRM_PROP_NAME_LEN]; | ||
85 | int count_values; | ||
86 | uint64_t *values; // store the blob lengths | ||
87 | int count_enums; | ||
88 | struct drm_mode_property_enum *enums; | ||
89 | int count_blobs; | ||
90 | uint32_t *blob_ids; // store the blob IDs | ||
91 | } drmModePropertyRes, *drmModePropertyPtr; | ||
92 | |||
93 | typedef struct _drmModeCrtc { | ||
94 | uint32_t crtc_id; | ||
95 | uint32_t buffer_id; /**< FB id to connect to 0 = disconnect */ | ||
96 | |||
97 | uint32_t x, y; /**< Position on the framebuffer */ | ||
98 | uint32_t width, height; | ||
99 | int mode_valid; | ||
100 | struct drm_mode_modeinfo mode; | ||
101 | |||
102 | int gamma_size; /**< Number of gamma stops */ | ||
103 | |||
104 | } drmModeCrtc, *drmModeCrtcPtr; | ||
105 | |||
106 | typedef struct _drmModeEncoder { | ||
107 | uint32_t encoder_id; | ||
108 | uint32_t encoder_type; | ||
109 | uint32_t crtc_id; | ||
110 | uint32_t possible_crtcs; | ||
111 | uint32_t possible_clones; | ||
112 | } drmModeEncoder, *drmModeEncoderPtr; | ||
113 | |||
114 | typedef enum { | ||
115 | DRM_MODE_CONNECTED = 1, | ||
116 | DRM_MODE_DISCONNECTED = 2, | ||
117 | DRM_MODE_UNKNOWNCONNECTION = 3 | ||
118 | } drmModeConnection; | ||
119 | |||
120 | typedef enum { | ||
121 | DRM_MODE_SUBPIXEL_UNKNOWN = 1, | ||
122 | DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2, | ||
123 | DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3, | ||
124 | DRM_MODE_SUBPIXEL_VERTICAL_RGB = 4, | ||
125 | DRM_MODE_SUBPIXEL_VERTICAL_BGR = 5, | ||
126 | DRM_MODE_SUBPIXEL_NONE = 6 | ||
127 | } drmModeSubPixel; | ||
128 | |||
129 | typedef struct _drmModeConnector { | ||
130 | uint32_t connector_id; | ||
131 | uint32_t encoder_id; /**< Encoder currently connected to */ | ||
132 | uint32_t connector_type; | ||
133 | uint32_t connector_type_id; | ||
134 | drmModeConnection connection; | ||
135 | uint32_t mmWidth, mmHeight; /**< HxW in millimeters */ | ||
136 | drmModeSubPixel subpixel; | ||
137 | |||
138 | int count_modes; | ||
139 | struct drm_mode_modeinfo *modes; | ||
140 | |||
141 | int count_props; | ||
142 | uint32_t *props; /**< List of property ids */ | ||
143 | uint64_t *prop_values; /**< List of property values */ | ||
144 | |||
145 | int count_encoders; | ||
146 | uint32_t *encoders; /**< List of encoder ids */ | ||
147 | } drmModeConnector, *drmModeConnectorPtr; | ||
148 | |||
149 | |||
150 | |||
151 | extern void drmModeFreeModeInfo( struct drm_mode_modeinfo *ptr ); | ||
152 | extern void drmModeFreeResources( drmModeResPtr ptr ); | ||
153 | extern void drmModeFreeFB( drmModeFBPtr ptr ); | ||
154 | extern void drmModeFreeCrtc( drmModeCrtcPtr ptr ); | ||
155 | extern void drmModeFreeConnector( drmModeConnectorPtr ptr ); | ||
156 | extern void drmModeFreeEncoder( drmModeEncoderPtr ptr ); | ||
157 | |||
158 | /** | ||
159 | * Retrives all of the resources associated with a card. | ||
160 | */ | ||
161 | extern drmModeResPtr drmModeGetResources(int fd); | ||
162 | |||
163 | /* | ||
164 | * FrameBuffer manipulation. | ||
165 | */ | ||
166 | |||
167 | /** | ||
168 | * Retrive information about framebuffer bufferId | ||
169 | */ | ||
170 | extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId); | ||
171 | |||
172 | /** | ||
173 | * Creates a new framebuffer with an buffer object as its scanout buffer. | ||
174 | */ | ||
175 | extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, | ||
176 | uint8_t bpp, uint32_t pitch, uint32_t bo_handle, | ||
177 | uint32_t *buf_id); | ||
178 | /** | ||
179 | * Destroies the given framebuffer. | ||
180 | */ | ||
181 | extern int drmModeRmFB(int fd, uint32_t bufferId); | ||
182 | |||
183 | /** | ||
184 | * Replace a framebuffer object with a new one - for resizing the screen. | ||
185 | */ | ||
186 | extern int drmModeReplaceFB(int fd, uint32_t buffer_id, | ||
187 | uint32_t width, uint32_t height, uint8_t depth, | ||
188 | uint8_t bpp, uint32_t pitch, uint32_t bo_handle); | ||
189 | |||
190 | /* | ||
191 | * Crtc functions | ||
192 | */ | ||
193 | |||
194 | /** | ||
195 | * Retrive information about the ctrt crtcId | ||
196 | */ | ||
197 | extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId); | ||
198 | |||
199 | /** | ||
200 | * Set the mode on a crtc crtcId with the given mode modeId. | ||
201 | */ | ||
202 | int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, | ||
203 | uint32_t x, uint32_t y, uint32_t *connectors, int count, | ||
204 | struct drm_mode_modeinfo *mode); | ||
205 | |||
206 | /* | ||
207 | * Cursor functions | ||
208 | */ | ||
209 | |||
210 | /** | ||
211 | * Set the cursor on crtc | ||
212 | */ | ||
213 | int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height); | ||
214 | |||
215 | /** | ||
216 | * Move the cursor on crtc | ||
217 | */ | ||
218 | int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y); | ||
219 | |||
220 | /** | ||
221 | * Encoder functions | ||
222 | */ | ||
223 | drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id); | ||
224 | |||
225 | /* | ||
226 | * Connector manipulation | ||
227 | */ | ||
228 | |||
229 | /** | ||
230 | * Retrive information about the connector connectorId. | ||
231 | */ | ||
232 | extern drmModeConnectorPtr drmModeGetConnector(int fd, | ||
233 | uint32_t connectorId); | ||
234 | |||
235 | /** | ||
236 | * Attaches the given mode to an connector. | ||
237 | */ | ||
238 | extern int drmModeAttachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info); | ||
239 | |||
240 | /** | ||
241 | * Detaches a mode from the connector | ||
242 | * must be unused, by the given mode. | ||
243 | */ | ||
244 | extern int drmModeDetachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info); | ||
245 | |||
246 | extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId); | ||
247 | extern void drmModeFreeProperty(drmModePropertyPtr ptr); | ||
248 | |||
249 | extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id); | ||
250 | extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr); | ||
251 | extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, | ||
252 | uint64_t value); | ||
253 | extern int drmCheckModesettingSupported(const char *busid); | ||
254 | |||
255 | extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, | ||
256 | uint16_t *red, uint16_t *green, uint16_t *blue); | ||
257 | extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, | ||
258 | 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 index 00000000..a43f1385 --- /dev/null +++ b/linux-core/drm_mode.h | |||
@@ -0,0 +1 @@ | |||
../shared-core/drm_mode.h \ No newline at end of file | |||
diff --git a/shared-core/Makefile.am b/shared-core/Makefile.am index 7193e527..99e90d64 100644 --- a/shared-core/Makefile.am +++ b/shared-core/Makefile.am | |||
@@ -25,6 +25,7 @@ | |||
25 | klibdrmincludedir = ${includedir}/drm | 25 | klibdrmincludedir = ${includedir}/drm |
26 | klibdrminclude_HEADERS = \ | 26 | klibdrminclude_HEADERS = \ |
27 | drm.h \ | 27 | drm.h \ |
28 | drm_mode.h \ | ||
28 | drm_sarea.h \ | 29 | drm_sarea.h \ |
29 | i915_drm.h \ | 30 | i915_drm.h \ |
30 | mach64_drm.h \ | 31 | mach64_drm.h \ |
diff --git a/shared-core/drm.h b/shared-core/drm.h index 507f0478..b97ba098 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h | |||
@@ -985,6 +985,8 @@ struct drm_gem_open { | |||
985 | uint64_t size; | 985 | uint64_t size; |
986 | }; | 986 | }; |
987 | 987 | ||
988 | #include "drm_mode.h" | ||
989 | |||
988 | /** | 990 | /** |
989 | * \name Ioctls Definitions | 991 | * \name Ioctls Definitions |
990 | */ | 992 | */ |
@@ -1027,6 +1029,9 @@ struct drm_gem_open { | |||
1027 | #define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) | 1029 | #define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) |
1028 | #define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) | 1030 | #define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) |
1029 | 1031 | ||
1032 | #define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) | ||
1033 | #define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) | ||
1034 | |||
1030 | #define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) | 1035 | #define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) |
1031 | #define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) | 1036 | #define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) |
1032 | #define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) | 1037 | #define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) |
@@ -1082,6 +1087,28 @@ struct drm_gem_open { | |||
1082 | #define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg) | 1087 | #define DRM_IOCTL_BO_VERSION DRM_IOR(0xd6, struct drm_bo_version_arg) |
1083 | #define DRM_IOCTL_MM_INFO DRM_IOWR(0xd7, struct drm_mm_info_arg) | 1088 | #define DRM_IOCTL_MM_INFO DRM_IOWR(0xd7, struct drm_mm_info_arg) |
1084 | 1089 | ||
1090 | #define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res) | ||
1091 | |||
1092 | #define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc) | ||
1093 | #define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc) | ||
1094 | #define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor) | ||
1095 | #define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut) | ||
1096 | #define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut) | ||
1097 | |||
1098 | #define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder) | ||
1099 | |||
1100 | #define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector) | ||
1101 | #define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) | ||
1102 | #define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) | ||
1103 | #define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property) | ||
1104 | #define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property) | ||
1105 | #define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob) | ||
1106 | |||
1107 | #define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd) | ||
1108 | #define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd) | ||
1109 | #define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, uint32_t) | ||
1110 | #define DRM_IOCTL_MODE_REPLACEFB DRM_IOWR(0xB0, struct drm_mode_fb_cmd) | ||
1111 | |||
1085 | /*@}*/ | 1112 | /*@}*/ |
1086 | 1113 | ||
1087 | /** | 1114 | /** |
diff --git a/shared-core/drm_mode.h b/shared-core/drm_mode.h new file mode 100644 index 00000000..601d2bd8 --- /dev/null +++ b/shared-core/drm_mode.h | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> | ||
3 | * Copyright (c) 2007 Jakob Bornecrantz <wallbraker@gmail.com> | ||
4 | * Copyright (c) 2008 Red Hat Inc. | ||
5 | * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA | ||
6 | * Copyright (c) 2007-2008 Intel Corporation | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice shall be included in | ||
16 | * all copies or substantial portions of the Software. | ||
17 | * | ||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
24 | * IN THE SOFTWARE. | ||
25 | */ | ||
26 | |||
27 | #ifndef _DRM_MODE_H | ||
28 | #define _DRM_MODE_H | ||
29 | |||
30 | #if !defined(__KERNEL__) && !defined(_KERNEL) | ||
31 | #include <stdint.h> | ||
32 | #else | ||
33 | #include <linux/kernel.h> | ||
34 | #endif | ||
35 | |||
36 | #define DRM_DISPLAY_INFO_LEN 32 | ||
37 | #define DRM_CONNECTOR_NAME_LEN 32 | ||
38 | #define DRM_DISPLAY_MODE_LEN 32 | ||
39 | #define DRM_PROP_NAME_LEN 32 | ||
40 | |||
41 | #define DRM_MODE_TYPE_BUILTIN (1<<0) | ||
42 | #define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN) | ||
43 | #define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN) | ||
44 | #define DRM_MODE_TYPE_PREFERRED (1<<3) | ||
45 | #define DRM_MODE_TYPE_DEFAULT (1<<4) | ||
46 | #define DRM_MODE_TYPE_USERDEF (1<<5) | ||
47 | #define DRM_MODE_TYPE_DRIVER (1<<6) | ||
48 | |||
49 | /* Video mode flags */ | ||
50 | /* bit compatible with the xorg definitions. */ | ||
51 | #define DRM_MODE_FLAG_PHSYNC (1<<0) | ||
52 | #define DRM_MODE_FLAG_NHSYNC (1<<1) | ||
53 | #define DRM_MODE_FLAG_PVSYNC (1<<2) | ||
54 | #define DRM_MODE_FLAG_NVSYNC (1<<3) | ||
55 | #define DRM_MODE_FLAG_INTERLACE (1<<4) | ||
56 | #define DRM_MODE_FLAG_DBLSCAN (1<<5) | ||
57 | #define DRM_MODE_FLAG_CSYNC (1<<6) | ||
58 | #define DRM_MODE_FLAG_PCSYNC (1<<7) | ||
59 | #define DRM_MODE_FLAG_NCSYNC (1<<8) | ||
60 | #define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ | ||
61 | #define DRM_MODE_FLAG_BCAST (1<<10) | ||
62 | #define DRM_MODE_FLAG_PIXMUX (1<<11) | ||
63 | #define DRM_MODE_FLAG_DBLCLK (1<<12) | ||
64 | #define DRM_MODE_FLAG_CLKDIV2 (1<<13) | ||
65 | |||
66 | /* DPMS flags */ | ||
67 | /* bit compatible with the xorg definitions. */ | ||
68 | #define DRM_MODE_DPMS_ON 0 | ||
69 | #define DRM_MODE_DPMS_STANDBY 1 | ||
70 | #define DRM_MODE_DPMS_SUSPEND 2 | ||
71 | #define DRM_MODE_DPMS_OFF 3 | ||
72 | |||
73 | /* Scaling mode options */ | ||
74 | #define DRM_MODE_SCALE_NON_GPU 0 | ||
75 | #define DRM_MODE_SCALE_FULLSCREEN 1 | ||
76 | #define DRM_MODE_SCALE_NO_SCALE 2 | ||
77 | #define DRM_MODE_SCALE_ASPECT 3 | ||
78 | |||
79 | /* Dithering mode options */ | ||
80 | #define DRM_MODE_DITHERING_OFF 0 | ||
81 | #define DRM_MODE_DITHERING_ON 1 | ||
82 | |||
83 | struct drm_mode_modeinfo { | ||
84 | uint32_t clock; | ||
85 | uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew; | ||
86 | uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan; | ||
87 | |||
88 | uint32_t vrefresh; /* vertical refresh * 1000 */ | ||
89 | |||
90 | uint32_t flags; | ||
91 | uint32_t type; | ||
92 | char name[DRM_DISPLAY_MODE_LEN]; | ||
93 | }; | ||
94 | |||
95 | struct drm_mode_card_res { | ||
96 | uint64_t fb_id_ptr; | ||
97 | uint64_t crtc_id_ptr; | ||
98 | uint64_t connector_id_ptr; | ||
99 | uint64_t encoder_id_ptr; | ||
100 | uint32_t count_fbs; | ||
101 | uint32_t count_crtcs; | ||
102 | uint32_t count_connectors; | ||
103 | uint32_t count_encoders; | ||
104 | uint32_t min_width, max_width; | ||
105 | uint32_t min_height, max_height; | ||
106 | }; | ||
107 | |||
108 | struct drm_mode_crtc { | ||
109 | uint64_t set_connectors_ptr; | ||
110 | uint32_t count_connectors; | ||
111 | |||
112 | uint32_t crtc_id; /**< Id */ | ||
113 | uint32_t fb_id; /**< Id of framebuffer */ | ||
114 | |||
115 | uint32_t x, y; /**< Position on the frameuffer */ | ||
116 | |||
117 | uint32_t gamma_size; | ||
118 | uint32_t mode_valid; | ||
119 | struct drm_mode_modeinfo mode; | ||
120 | }; | ||
121 | |||
122 | #define DRM_MODE_ENCODER_NONE 0 | ||
123 | #define DRM_MODE_ENCODER_DAC 1 | ||
124 | #define DRM_MODE_ENCODER_TMDS 2 | ||
125 | #define DRM_MODE_ENCODER_LVDS 3 | ||
126 | #define DRM_MODE_ENCODER_TVDAC 4 | ||
127 | |||
128 | struct drm_mode_get_encoder { | ||
129 | uint32_t encoder_id; | ||
130 | uint32_t encoder_type; | ||
131 | |||
132 | uint32_t crtc_id; /**< Id of crtc */ | ||
133 | |||
134 | uint32_t possible_crtcs; | ||
135 | uint32_t possible_clones; | ||
136 | }; | ||
137 | |||
138 | /* This is for connectors with multiple signal types. */ | ||
139 | /* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ | ||
140 | #define DRM_MODE_SUBCONNECTOR_Automatic 0 | ||
141 | #define DRM_MODE_SUBCONNECTOR_Unknown 0 | ||
142 | #define DRM_MODE_SUBCONNECTOR_DVID 3 | ||
143 | #define DRM_MODE_SUBCONNECTOR_DVIA 4 | ||
144 | #define DRM_MODE_SUBCONNECTOR_Composite 5 | ||
145 | #define DRM_MODE_SUBCONNECTOR_SVIDEO 6 | ||
146 | #define DRM_MODE_SUBCONNECTOR_Component 8 | ||
147 | |||
148 | #define DRM_MODE_CONNECTOR_Unknown 0 | ||
149 | #define DRM_MODE_CONNECTOR_VGA 1 | ||
150 | #define DRM_MODE_CONNECTOR_DVII 2 | ||
151 | #define DRM_MODE_CONNECTOR_DVID 3 | ||
152 | #define DRM_MODE_CONNECTOR_DVIA 4 | ||
153 | #define DRM_MODE_CONNECTOR_Composite 5 | ||
154 | #define DRM_MODE_CONNECTOR_SVIDEO 6 | ||
155 | #define DRM_MODE_CONNECTOR_LVDS 7 | ||
156 | #define DRM_MODE_CONNECTOR_Component 8 | ||
157 | #define DRM_MODE_CONNECTOR_9PinDIN 9 | ||
158 | #define DRM_MODE_CONNECTOR_DisplayPort 10 | ||
159 | #define DRM_MODE_CONNECTOR_HDMIA 11 | ||
160 | #define DRM_MODE_CONNECTOR_HDMIB 12 | ||
161 | |||
162 | struct drm_mode_get_connector { | ||
163 | |||
164 | uint64_t encoders_ptr; | ||
165 | uint64_t modes_ptr; | ||
166 | uint64_t props_ptr; | ||
167 | uint64_t prop_values_ptr; | ||
168 | |||
169 | uint32_t count_modes; | ||
170 | uint32_t count_props; | ||
171 | uint32_t count_encoders; | ||
172 | |||
173 | uint32_t encoder_id; /**< Current Encoder */ | ||
174 | uint32_t connector_id; /**< Id */ | ||
175 | uint32_t connector_type; | ||
176 | uint32_t connector_type_id; | ||
177 | |||
178 | uint32_t connection; | ||
179 | uint32_t mm_width, mm_height; /**< HxW in millimeters */ | ||
180 | uint32_t subpixel; | ||
181 | }; | ||
182 | |||
183 | #define DRM_MODE_PROP_PENDING (1<<0) | ||
184 | #define DRM_MODE_PROP_RANGE (1<<1) | ||
185 | #define DRM_MODE_PROP_IMMUTABLE (1<<2) | ||
186 | #define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ | ||
187 | #define DRM_MODE_PROP_BLOB (1<<4) | ||
188 | |||
189 | struct drm_mode_property_enum { | ||
190 | uint64_t value; | ||
191 | char name[DRM_PROP_NAME_LEN]; | ||
192 | }; | ||
193 | |||
194 | struct drm_mode_get_property { | ||
195 | uint64_t values_ptr; /* values and blob lengths */ | ||
196 | uint64_t enum_blob_ptr; /* enum and blob id ptrs */ | ||
197 | |||
198 | uint32_t prop_id; | ||
199 | uint32_t flags; | ||
200 | char name[DRM_PROP_NAME_LEN]; | ||
201 | |||
202 | uint32_t count_values; | ||
203 | uint32_t count_enum_blobs; | ||
204 | }; | ||
205 | |||
206 | struct drm_mode_connector_set_property { | ||
207 | uint64_t value; | ||
208 | uint32_t prop_id; | ||
209 | uint32_t connector_id; | ||
210 | }; | ||
211 | |||
212 | struct drm_mode_get_blob { | ||
213 | uint32_t blob_id; | ||
214 | uint32_t length; | ||
215 | uint64_t data; | ||
216 | }; | ||
217 | |||
218 | struct drm_mode_fb_cmd { | ||
219 | uint32_t fb_id; | ||
220 | uint32_t width, height; | ||
221 | uint32_t pitch; | ||
222 | uint32_t bpp; | ||
223 | uint32_t depth; | ||
224 | /* driver specific handle */ | ||
225 | uint32_t handle; | ||
226 | }; | ||
227 | |||
228 | struct drm_mode_mode_cmd { | ||
229 | uint32_t connector_id; | ||
230 | struct drm_mode_modeinfo mode; | ||
231 | }; | ||
232 | |||
233 | #define DRM_MODE_CURSOR_BO (1<<0) | ||
234 | #define DRM_MODE_CURSOR_MOVE (1<<1) | ||
235 | |||
236 | /* | ||
237 | * depending on the value in flags diffrent members are used. | ||
238 | * | ||
239 | * CURSOR_BO uses | ||
240 | * crtc | ||
241 | * width | ||
242 | * height | ||
243 | * handle - if 0 turns the cursor of | ||
244 | * | ||
245 | * CURSOR_MOVE uses | ||
246 | * crtc | ||
247 | * x | ||
248 | * y | ||
249 | */ | ||
250 | struct drm_mode_cursor { | ||
251 | uint32_t flags; | ||
252 | uint32_t crtc_id; | ||
253 | int32_t x; | ||
254 | int32_t y; | ||
255 | uint32_t width; | ||
256 | uint32_t height; | ||
257 | /* driver specific handle */ | ||
258 | uint32_t handle; | ||
259 | }; | ||
260 | |||
261 | struct drm_mode_crtc_lut { | ||
262 | uint32_t crtc_id; | ||
263 | uint32_t gamma_size; | ||
264 | |||
265 | /* pointers to arrays */ | ||
266 | uint64_t red; | ||
267 | uint64_t green; | ||
268 | uint64_t blue; | ||
269 | }; | ||
270 | |||
271 | #endif | ||
diff --git a/tests/Makefile.am b/tests/Makefile.am index 95f0f22e..02b2ef0a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am | |||
@@ -15,6 +15,10 @@ libdrmtest_la_LIBADD = \ | |||
15 | 15 | ||
16 | LDADD = libdrmtest.la | 16 | LDADD = libdrmtest.la |
17 | 17 | ||
18 | noinst_SUBDIRS = \ | ||
19 | modeprint \ | ||
20 | modetest | ||
21 | |||
18 | TESTS = auth \ | 22 | TESTS = auth \ |
19 | openclose \ | 23 | openclose \ |
20 | getversion \ | 24 | getversion \ |
diff --git a/tests/dristat.c b/tests/dristat.c index 89853164..48c3b51b 100644 --- a/tests/dristat.c +++ b/tests/dristat.c | |||
@@ -263,7 +263,7 @@ int main(int argc, char **argv) | |||
263 | 263 | ||
264 | for (i = 0; i < 16; i++) if (!minor || i == minor) { | 264 | for (i = 0; i < 16; i++) if (!minor || i == minor) { |
265 | sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i); | 265 | sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i); |
266 | fd = drmOpenMinor(i, 1); | 266 | fd = drmOpenMinor(i, 1, DRM_NODE_RENDER); |
267 | if (fd >= 0) { | 267 | if (fd >= 0) { |
268 | printf("%s\n", buf); | 268 | printf("%s\n", buf); |
269 | if (mask & DRM_BUSID) getbusid(fd); | 269 | if (mask & DRM_BUSID) getbusid(fd); |
diff --git a/tests/modeprint/Makefile b/tests/modeprint/Makefile new file mode 100644 index 00000000..70788dc9 --- /dev/null +++ b/tests/modeprint/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | |||
2 | all: app | ||
3 | |||
4 | #CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ | ||
5 | # -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ | ||
6 | |||
7 | app: modeprint.c | ||
8 | @gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm modeprint.c | ||
9 | |||
10 | clean: | ||
11 | @rm -f app | ||
12 | |||
13 | run: app | ||
14 | @sudo ./test | ||
diff --git a/tests/modeprint/app b/tests/modeprint/app new file mode 100755 index 00000000..82085c85 --- /dev/null +++ b/tests/modeprint/app | |||
Binary files differ | |||
diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c new file mode 100644 index 00000000..595d4447 --- /dev/null +++ b/tests/modeprint/modeprint.c | |||
@@ -0,0 +1,402 @@ | |||
1 | /* | ||
2 | * \file modedemo.c | ||
3 | * Test program to dump DRM kernel mode setting related information. | ||
4 | * Queries the kernel for all available information and dumps it to stdout. | ||
5 | * | ||
6 | * \author Jakob Bornecrantz <wallbraker@gmail.com> | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. | ||
11 | * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> | ||
12 | * | ||
13 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
14 | * copy of this software and associated documentation files (the "Software"), | ||
15 | * to deal in the Software without restriction, including without limitation | ||
16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
17 | * and/or sell copies of the Software, and to permit persons to whom the | ||
18 | * Software is furnished to do so, subject to the following conditions: | ||
19 | * | ||
20 | * The above copyright notice and this permission notice shall be included in | ||
21 | * all copies or substantial portions of the Software. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
28 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
29 | * IN THE SOFTWARE. | ||
30 | * | ||
31 | */ | ||
32 | |||
33 | #include <assert.h> | ||
34 | #include <stdio.h> | ||
35 | #include <stdlib.h> | ||
36 | #include <stdint.h> | ||
37 | #include <unistd.h> | ||
38 | #include <string.h> | ||
39 | |||
40 | #include "xf86drm.h" | ||
41 | #include "xf86drmMode.h" | ||
42 | |||
43 | int connectors; | ||
44 | int full_props; | ||
45 | int edid; | ||
46 | int modes; | ||
47 | int full_modes; | ||
48 | int encoders; | ||
49 | int crtcs; | ||
50 | int fbs; | ||
51 | char *module_name; | ||
52 | |||
53 | const char* getConnectionText(drmModeConnection conn) | ||
54 | { | ||
55 | switch (conn) { | ||
56 | case DRM_MODE_CONNECTED: | ||
57 | return "connected"; | ||
58 | case DRM_MODE_DISCONNECTED: | ||
59 | return "disconnected"; | ||
60 | default: | ||
61 | return "unknown"; | ||
62 | } | ||
63 | |||
64 | } | ||
65 | |||
66 | int printMode(struct drm_mode_modeinfo *mode) | ||
67 | { | ||
68 | if (full_modes) { | ||
69 | printf("Mode: %s\n", mode->name); | ||
70 | printf("\tclock : %i\n", mode->clock); | ||
71 | printf("\thdisplay : %i\n", mode->hdisplay); | ||
72 | printf("\thsync_start : %i\n", mode->hsync_start); | ||
73 | printf("\thsync_end : %i\n", mode->hsync_end); | ||
74 | printf("\thtotal : %i\n", mode->htotal); | ||
75 | printf("\thskew : %i\n", mode->hskew); | ||
76 | printf("\tvdisplay : %i\n", mode->vdisplay); | ||
77 | printf("\tvsync_start : %i\n", mode->vsync_start); | ||
78 | printf("\tvsync_end : %i\n", mode->vsync_end); | ||
79 | printf("\tvtotal : %i\n", mode->vtotal); | ||
80 | printf("\tvscan : %i\n", mode->vscan); | ||
81 | printf("\tvrefresh : %i\n", mode->vrefresh); | ||
82 | printf("\tflags : %i\n", mode->flags); | ||
83 | } else { | ||
84 | printf("Mode: \"%s\" %ix%i %.0f\n", mode->name, | ||
85 | mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000.0); | ||
86 | } | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, uint64_t value) | ||
91 | { | ||
92 | const unsigned char *name = NULL; | ||
93 | int j; | ||
94 | |||
95 | printf("Property: %s\n", props->name); | ||
96 | printf("\tid : %i\n", props->prop_id); | ||
97 | printf("\tflags : %i\n", props->flags); | ||
98 | printf("\tcount_values : %d\n", props->count_values); | ||
99 | |||
100 | |||
101 | if (props->count_values) { | ||
102 | printf("\tvalues :"); | ||
103 | for (j = 0; j < props->count_values; j++) | ||
104 | printf(" %lld", props->values[j]); | ||
105 | printf("\n"); | ||
106 | } | ||
107 | |||
108 | |||
109 | printf("\tcount_enums : %d\n", props->count_enums); | ||
110 | |||
111 | if (props->flags & DRM_MODE_PROP_BLOB) { | ||
112 | drmModePropertyBlobPtr blob; | ||
113 | |||
114 | blob = drmModeGetPropertyBlob(fd, value); | ||
115 | if (blob) { | ||
116 | printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data); | ||
117 | drmModeFreePropertyBlob(blob); | ||
118 | } else { | ||
119 | printf("error getting blob %lld\n", value); | ||
120 | } | ||
121 | |||
122 | } else { | ||
123 | if (!strncmp(props->name, "DPMS", 4)) | ||
124 | ; | ||
125 | |||
126 | for (j = 0; j < props->count_enums; j++) { | ||
127 | printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name); | ||
128 | if (props->enums[j].value == value) | ||
129 | name = props->enums[j].name; | ||
130 | } | ||
131 | |||
132 | if (props->count_enums && name) { | ||
133 | printf("\tcon_value : %s\n", name); | ||
134 | } else { | ||
135 | printf("\tcon_value : %lld\n", value); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id) | ||
143 | { | ||
144 | int i = 0; | ||
145 | struct drm_mode_modeinfo *mode = NULL; | ||
146 | drmModePropertyPtr props; | ||
147 | |||
148 | printf("Connector: %d-%d\n", connector->connector_type, connector->connector_type_id); | ||
149 | printf("\tid : %i\n", id); | ||
150 | printf("\tencoder id : %i\n", connector->encoder_id); | ||
151 | printf("\tconn : %s\n", getConnectionText(connector->connection)); | ||
152 | printf("\tsize : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight); | ||
153 | printf("\tcount_modes : %i\n", connector->count_modes); | ||
154 | printf("\tcount_props : %i\n", connector->count_props); | ||
155 | if (connector->count_props) { | ||
156 | printf("\tprops :"); | ||
157 | for (i = 0; i < connector->count_props; i++) | ||
158 | printf(" %i", connector->props[i]); | ||
159 | printf("\n"); | ||
160 | } | ||
161 | |||
162 | printf("\tcount_encoders : %i\n", connector->count_encoders); | ||
163 | if (connector->count_encoders) { | ||
164 | printf("\tencoders :"); | ||
165 | for (i = 0; i < connector->count_encoders; i++) | ||
166 | printf(" %i", connector->encoders[i]); | ||
167 | printf("\n"); | ||
168 | } | ||
169 | |||
170 | if (modes) { | ||
171 | for (i = 0; i < connector->count_modes; i++) { | ||
172 | mode = &connector->modes[i]; | ||
173 | printMode(mode); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | if (full_props) { | ||
178 | for (i = 0; i < connector->count_props; i++) { | ||
179 | props = drmModeGetProperty(fd, connector->props[i]); | ||
180 | if (props) { | ||
181 | printProperty(fd, res, props, connector->prop_values[i]); | ||
182 | drmModeFreeProperty(props); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id) | ||
191 | { | ||
192 | printf("Encoder\n"); | ||
193 | printf("\tid :%i\n", id); | ||
194 | printf("\tcrtc_id :%d\n", encoder->crtc_id); | ||
195 | printf("\ttype :%d\n", encoder->encoder_type); | ||
196 | printf("\tpossible_crtcs :%d\n", encoder->possible_crtcs); | ||
197 | printf("\tpossible_clones :%d\n", encoder->possible_clones); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id) | ||
202 | { | ||
203 | printf("Crtc\n"); | ||
204 | printf("\tid : %i\n", id); | ||
205 | printf("\tx : %i\n", crtc->x); | ||
206 | printf("\ty : %i\n", crtc->y); | ||
207 | printf("\twidth : %i\n", crtc->width); | ||
208 | printf("\theight : %i\n", crtc->height); | ||
209 | printf("\tmode : %p\n", &crtc->mode); | ||
210 | printf("\tgamma size : %d\n", crtc->gamma_size); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb) | ||
216 | { | ||
217 | printf("Framebuffer\n"); | ||
218 | printf("\thandle : %i\n", fb->handle); | ||
219 | printf("\twidth : %i\n", fb->width); | ||
220 | printf("\theight : %i\n", fb->height); | ||
221 | printf("\tpitch : %i\n", fb->pitch);; | ||
222 | printf("\tbpp : %i\n", fb->bpp); | ||
223 | printf("\tdepth : %i\n", fb->depth); | ||
224 | printf("\tbuffer_id : %i\n", fb->handle); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | int printRes(int fd, drmModeResPtr res) | ||
230 | { | ||
231 | int i; | ||
232 | drmModeFBPtr fb; | ||
233 | drmModeCrtcPtr crtc; | ||
234 | drmModeEncoderPtr encoder; | ||
235 | drmModeConnectorPtr connector; | ||
236 | |||
237 | printf("Resources\n\n"); | ||
238 | |||
239 | printf("count_connectors : %i\n", res->count_connectors); | ||
240 | printf("count_encoders : %i\n", res->count_encoders); | ||
241 | printf("count_crtcs : %i\n", res->count_crtcs); | ||
242 | printf("count_fbs : %i\n", res->count_fbs); | ||
243 | |||
244 | printf("\n"); | ||
245 | |||
246 | if (connectors) { | ||
247 | for (i = 0; i < res->count_connectors; i++) { | ||
248 | connector = drmModeGetConnector(fd, res->connectors[i]); | ||
249 | |||
250 | if (!connector) | ||
251 | printf("Could not get connector %i\n", res->connectors[i]); | ||
252 | else { | ||
253 | printConnector(fd, res, connector, res->connectors[i]); | ||
254 | drmModeFreeConnector(connector); | ||
255 | } | ||
256 | } | ||
257 | printf("\n"); | ||
258 | } | ||
259 | |||
260 | |||
261 | if (encoders) { | ||
262 | for (i = 0; i < res->count_encoders; i++) { | ||
263 | encoder = drmModeGetEncoder(fd, res->encoders[i]); | ||
264 | |||
265 | if (!encoder) | ||
266 | printf("Could not get encoder %i\n", res->encoders[i]); | ||
267 | else { | ||
268 | printEncoder(fd, res, encoder, res->encoders[i]); | ||
269 | drmModeFreeEncoder(encoder); | ||
270 | } | ||
271 | } | ||
272 | printf("\n"); | ||
273 | } | ||
274 | |||
275 | if (crtcs) { | ||
276 | for (i = 0; i < res->count_crtcs; i++) { | ||
277 | crtc = drmModeGetCrtc(fd, res->crtcs[i]); | ||
278 | |||
279 | if (!crtc) | ||
280 | printf("Could not get crtc %i\n", res->crtcs[i]); | ||
281 | else { | ||
282 | printCrtc(fd, res, crtc, res->crtcs[i]); | ||
283 | drmModeFreeCrtc(crtc); | ||
284 | } | ||
285 | } | ||
286 | printf("\n"); | ||
287 | } | ||
288 | |||
289 | if (fbs) { | ||
290 | for (i = 0; i < res->count_fbs; i++) { | ||
291 | fb = drmModeGetFB(fd, res->fbs[i]); | ||
292 | |||
293 | if (!fb) | ||
294 | printf("Could not get fb %i\n", res->fbs[i]); | ||
295 | else { | ||
296 | printFrameBuffer(fd, res, fb); | ||
297 | drmModeFreeFB(fb); | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | void args(int argc, char **argv) | ||
306 | { | ||
307 | int i; | ||
308 | |||
309 | fbs = 0; | ||
310 | edid = 0; | ||
311 | crtcs = 0; | ||
312 | modes = 0; | ||
313 | encoders = 0; | ||
314 | full_modes = 0; | ||
315 | full_props = 0; | ||
316 | connectors = 0; | ||
317 | |||
318 | module_name = argv[1]; | ||
319 | |||
320 | for (i = 2; i < argc; i++) { | ||
321 | if (strcmp(argv[i], "-fb") == 0) { | ||
322 | fbs = 1; | ||
323 | } else if (strcmp(argv[i], "-crtcs") == 0) { | ||
324 | crtcs = 1; | ||
325 | } else if (strcmp(argv[i], "-cons") == 0) { | ||
326 | connectors = 1; | ||
327 | modes = 1; | ||
328 | } else if (strcmp(argv[i], "-modes") == 0) { | ||
329 | connectors = 1; | ||
330 | modes = 1; | ||
331 | } else if (strcmp(argv[i], "-full") == 0) { | ||
332 | connectors = 1; | ||
333 | modes = 1; | ||
334 | full_modes = 1; | ||
335 | } else if (strcmp(argv[i], "-props") == 0) { | ||
336 | connectors = 1; | ||
337 | full_props = 1; | ||
338 | } else if (strcmp(argv[i], "-edids") == 0) { | ||
339 | connectors = 1; | ||
340 | edid = 1; | ||
341 | } else if (strcmp(argv[i], "-encoders") == 0) { | ||
342 | encoders = 1; | ||
343 | } else if (strcmp(argv[i], "-v") == 0) { | ||
344 | fbs = 1; | ||
345 | edid = 1; | ||
346 | crtcs = 1; | ||
347 | modes = 1; | ||
348 | encoders = 1; | ||
349 | full_modes = 1; | ||
350 | full_props = 1; | ||
351 | connectors = 1; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | if (argc == 2) { | ||
356 | fbs = 1; | ||
357 | edid = 1; | ||
358 | crtcs = 1; | ||
359 | modes = 1; | ||
360 | encoders = 1; | ||
361 | full_modes = 0; | ||
362 | full_props = 0; | ||
363 | connectors = 1; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | int main(int argc, char **argv) | ||
368 | { | ||
369 | int fd; | ||
370 | drmModeResPtr res; | ||
371 | |||
372 | if (argc == 1) { | ||
373 | printf("Please add modulename as first argument\n"); | ||
374 | return 1; | ||
375 | } | ||
376 | |||
377 | args(argc, argv); | ||
378 | |||
379 | printf("Starting test\n"); | ||
380 | |||
381 | fd = drmOpen(module_name, NULL); | ||
382 | |||
383 | if (fd < 0) { | ||
384 | printf("Failed to open the card fd (%d)\n",fd); | ||
385 | return 1; | ||
386 | } | ||
387 | |||
388 | res = drmModeGetResources(fd); | ||
389 | if (res == 0) { | ||
390 | printf("Failed to get resources from card\n"); | ||
391 | drmClose(fd); | ||
392 | return 1; | ||
393 | } | ||
394 | |||
395 | printRes(fd, res); | ||
396 | |||
397 | drmModeFreeResources(res); | ||
398 | |||
399 | printf("Ok\n"); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
diff --git a/tests/modeprint/test b/tests/modeprint/test new file mode 100644 index 00000000..bd1952cc --- /dev/null +++ b/tests/modeprint/test | |||
@@ -0,0 +1 @@ | |||
LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@ | |||
diff --git a/tests/modetest/Makefile b/tests/modetest/Makefile new file mode 100644 index 00000000..8583ae82 --- /dev/null +++ b/tests/modetest/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | |||
2 | all: app | ||
3 | |||
4 | #CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ | ||
5 | # -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ | ||
6 | |||
7 | app: modetest.c | ||
8 | 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 | ||
9 | |||
10 | clean: | ||
11 | @rm -f app | ||
12 | |||
13 | run: app | ||
14 | sudo ./test | ||
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c new file mode 100644 index 00000000..e5a16e1a --- /dev/null +++ b/tests/modetest/modetest.c | |||
@@ -0,0 +1,449 @@ | |||
1 | /* | ||
2 | * DRM based mode setting test program | ||
3 | * Copyright 2008 Tungsten Graphics | ||
4 | * Jakob Bornecrantz <jakob@tungstengraphics.com> | ||
5 | * Copyright 2008 Intel Corporation | ||
6 | * Jesse Barnes <jesse.barnes@intel.com> | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice shall be included in | ||
16 | * all copies or substantial portions of the Software. | ||
17 | * | ||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
24 | * IN THE SOFTWARE. | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * This fairly simple test program dumps output in a similar format to the | ||
29 | * "xrandr" tool everyone knows & loves. It's necessarily slightly different | ||
30 | * since the kernel separates outputs into encoder and connector structures, | ||
31 | * each with their own unique ID. The program also allows test testing of the | ||
32 | * memory management and mode setting APIs by allowing the user to specify a | ||
33 | * connector and mode to use for mode setting. If all works as expected, a | ||
34 | * blue background should be painted on the monitor attached to the specified | ||
35 | * connector after the selected mode is set. | ||
36 | * | ||
37 | * TODO: use cairo to write the mode info on the selected output once | ||
38 | * the mode has been programmed, along with possible test patterns. | ||
39 | */ | ||
40 | #include <assert.h> | ||
41 | #include <stdio.h> | ||
42 | #include <stdlib.h> | ||
43 | #include <stdint.h> | ||
44 | #include <unistd.h> | ||
45 | #include <string.h> | ||
46 | #include <errno.h> | ||
47 | |||
48 | #include "xf86drm.h" | ||
49 | #include "xf86drmMode.h" | ||
50 | #include "intel_bufmgr.h" | ||
51 | |||
52 | drmModeRes *resources; | ||
53 | int fd, modes; | ||
54 | |||
55 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) | ||
56 | |||
57 | struct type_name { | ||
58 | int type; | ||
59 | char *name; | ||
60 | }; | ||
61 | |||
62 | #define type_name_fn(res) \ | ||
63 | char * res##_str(int type) { \ | ||
64 | int i; \ | ||
65 | for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \ | ||
66 | if (res##_names[i].type == type) \ | ||
67 | return res##_names[i].name; \ | ||
68 | } \ | ||
69 | return "(invalid)"; \ | ||
70 | } | ||
71 | |||
72 | struct type_name encoder_type_names[] = { | ||
73 | { DRM_MODE_ENCODER_NONE, "none" }, | ||
74 | { DRM_MODE_ENCODER_DAC, "DAC" }, | ||
75 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, | ||
76 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, | ||
77 | { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, | ||
78 | }; | ||
79 | |||
80 | type_name_fn(encoder_type) | ||
81 | |||
82 | struct type_name connector_status_names[] = { | ||
83 | { DRM_MODE_CONNECTED, "connected" }, | ||
84 | { DRM_MODE_DISCONNECTED, "disconnected" }, | ||
85 | { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, | ||
86 | }; | ||
87 | |||
88 | type_name_fn(connector_status) | ||
89 | |||
90 | struct type_name connector_type_names[] = { | ||
91 | { DRM_MODE_CONNECTOR_Unknown, "unknown" }, | ||
92 | { DRM_MODE_CONNECTOR_VGA, "VGA" }, | ||
93 | { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, | ||
94 | { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, | ||
95 | { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, | ||
96 | { DRM_MODE_CONNECTOR_Composite, "composite" }, | ||
97 | { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, | ||
98 | { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, | ||
99 | { DRM_MODE_CONNECTOR_Component, "component" }, | ||
100 | { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, | ||
101 | { DRM_MODE_CONNECTOR_DisplayPort, "displayport" }, | ||
102 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, | ||
103 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, | ||
104 | }; | ||
105 | |||
106 | type_name_fn(connector_type) | ||
107 | |||
108 | void dump_encoders(void) | ||
109 | { | ||
110 | drmModeEncoder *encoder; | ||
111 | int i; | ||
112 | |||
113 | printf("Encoders:\n"); | ||
114 | printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n"); | ||
115 | for (i = 0; i < resources->count_encoders; i++) { | ||
116 | encoder = drmModeGetEncoder(fd, resources->encoders[i]); | ||
117 | |||
118 | if (!encoder) { | ||
119 | fprintf(stderr, "could not get encoder %i: %s\n", | ||
120 | resources->encoders[i], strerror(errno)); | ||
121 | continue; | ||
122 | } | ||
123 | printf("%d\t%d\t%s\t0x%08x\t0x%08x\n", | ||
124 | encoder->encoder_id, | ||
125 | encoder->crtc_id, | ||
126 | encoder_type_str(encoder->encoder_type), | ||
127 | encoder->possible_crtcs, | ||
128 | encoder->possible_clones); | ||
129 | drmModeFreeEncoder(encoder); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | void dump_connectors(void) | ||
134 | { | ||
135 | drmModeConnector *connector; | ||
136 | int i, j; | ||
137 | |||
138 | printf("Connectors:\n"); | ||
139 | printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n"); | ||
140 | for (i = 0; i < resources->count_connectors; i++) { | ||
141 | connector = drmModeGetConnector(fd, resources->connectors[i]); | ||
142 | |||
143 | if (!connector) { | ||
144 | fprintf(stderr, "could not get connector %i: %s\n", | ||
145 | resources->connectors[i], strerror(errno)); | ||
146 | continue; | ||
147 | } | ||
148 | |||
149 | printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n", | ||
150 | connector->connector_id, | ||
151 | connector->encoder_id, | ||
152 | connector_status_str(connector->connection), | ||
153 | connector_type_str(connector->connector_type), | ||
154 | connector->mmWidth, connector->mmHeight, | ||
155 | connector->count_modes); | ||
156 | |||
157 | if (!connector->count_modes) | ||
158 | continue; | ||
159 | |||
160 | printf(" modes:\n"); | ||
161 | printf(" name refresh (Hz) hdisp hss hse htot vdisp " | ||
162 | "vss vse vtot)\n"); | ||
163 | for (j = 0; j < connector->count_modes; j++) { | ||
164 | struct drm_mode_modeinfo *mode; | ||
165 | |||
166 | mode = &connector->modes[j]; | ||
167 | printf(" %s %.02f %d %d %d %d %d %d %d %d\n", | ||
168 | mode->name, | ||
169 | (float)mode->vrefresh / 1000, | ||
170 | mode->hdisplay, | ||
171 | mode->hsync_start, | ||
172 | mode->hsync_end, | ||
173 | mode->htotal, | ||
174 | mode->vdisplay, | ||
175 | mode->vsync_start, | ||
176 | mode->vsync_end, | ||
177 | mode->vtotal); | ||
178 | } | ||
179 | drmModeFreeConnector(connector); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | void dump_crtcs(void) | ||
184 | { | ||
185 | drmModeCrtc *crtc; | ||
186 | int i; | ||
187 | |||
188 | for (i = 0; i < resources->count_crtcs; i++) { | ||
189 | crtc = drmModeGetCrtc(fd, resources->crtcs[i]); | ||
190 | |||
191 | if (!crtc) { | ||
192 | fprintf(stderr, "could not get crtc %i: %s\n", | ||
193 | resources->crtcs[i], strerror(errno)); | ||
194 | continue; | ||
195 | } | ||
196 | drmModeFreeCrtc(crtc); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | void dump_framebuffers(void) | ||
201 | { | ||
202 | drmModeFB *fb; | ||
203 | int i; | ||
204 | |||
205 | for (i = 0; i < resources->count_fbs; i++) { | ||
206 | fb = drmModeGetFB(fd, resources->fbs[i]); | ||
207 | |||
208 | if (!fb) { | ||
209 | fprintf(stderr, "could not get fb %i: %s\n", | ||
210 | resources->fbs[i], strerror(errno)); | ||
211 | continue; | ||
212 | } | ||
213 | drmModeFreeFB(fb); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * Mode setting with the kernel interfaces is a bit of a chore. | ||
219 | * First you have to find the connector in question and make sure the | ||
220 | * requested mode is available. | ||
221 | * Then you need to find the encoder attached to that connector so you | ||
222 | * can bind it with a free crtc. | ||
223 | */ | ||
224 | void set_mode(int connector_id, char *mode_str) | ||
225 | { | ||
226 | drmModeConnector *connector; | ||
227 | drmModeEncoder *encoder = NULL; | ||
228 | struct drm_mode_modeinfo *mode = NULL; | ||
229 | drm_intel_bufmgr *bufmgr; | ||
230 | drm_intel_bo *bo; | ||
231 | unsigned int fb_id, *fb_ptr; | ||
232 | int i, j, size, ret, width, height; | ||
233 | |||
234 | /* First, find the connector & mode */ | ||
235 | for (i = 0; i < resources->count_connectors; i++) { | ||
236 | connector = drmModeGetConnector(fd, resources->connectors[i]); | ||
237 | |||
238 | if (!connector) { | ||
239 | fprintf(stderr, "could not get connector %i: %s\n", | ||
240 | resources->connectors[i], strerror(errno)); | ||
241 | drmModeFreeConnector(connector); | ||
242 | continue; | ||
243 | } | ||
244 | |||
245 | if (!connector->count_modes) { | ||
246 | drmModeFreeConnector(connector); | ||
247 | continue; | ||
248 | } | ||
249 | |||
250 | if (connector->connector_id != connector_id) { | ||
251 | drmModeFreeConnector(connector); | ||
252 | continue; | ||
253 | } | ||
254 | |||
255 | for (j = 0; j < connector->count_modes; j++) { | ||
256 | mode = &connector->modes[j]; | ||
257 | if (!strcmp(mode->name, mode_str)) | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | /* Found it, break out */ | ||
262 | if (mode) | ||
263 | break; | ||
264 | |||
265 | drmModeFreeConnector(connector); | ||
266 | } | ||
267 | |||
268 | if (!mode) { | ||
269 | fprintf(stderr, "failed to find mode \"%s\"\n", mode_str); | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | width = mode->hdisplay; | ||
274 | height = mode->vdisplay; | ||
275 | |||
276 | /* Now get the encoder */ | ||
277 | for (i = 0; i < resources->count_encoders; i++) { | ||
278 | encoder = drmModeGetEncoder(fd, resources->encoders[i]); | ||
279 | |||
280 | if (!encoder) { | ||
281 | fprintf(stderr, "could not get encoder %i: %s\n", | ||
282 | resources->encoders[i], strerror(errno)); | ||
283 | drmModeFreeEncoder(encoder); | ||
284 | continue; | ||
285 | } | ||
286 | |||
287 | if (encoder->encoder_id == connector->encoder_id) | ||
288 | break; | ||
289 | |||
290 | drmModeFreeEncoder(encoder); | ||
291 | } | ||
292 | |||
293 | bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20); | ||
294 | if (!bufmgr) { | ||
295 | fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno)); | ||
296 | return; | ||
297 | } | ||
298 | |||
299 | /* Mode size at 32 bpp */ | ||
300 | size = width * height * 4; | ||
301 | |||
302 | bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096); | ||
303 | if (!bo) { | ||
304 | fprintf(stderr, "failed to alloc buffer: %s\n", | ||
305 | strerror(errno)); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | ret = drm_intel_bo_pin(bo, 4096); | ||
310 | if (ret) { | ||
311 | fprintf(stderr, "failed to pin buffer: %s\n", strerror(errno)); | ||
312 | return; | ||
313 | } | ||
314 | |||
315 | ret = drm_intel_gem_bo_map_gtt(bo); | ||
316 | if (ret) { | ||
317 | fprintf(stderr, "failed to GTT map buffer: %s\n", | ||
318 | strerror(errno)); | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | fb_ptr = bo->virtual; | ||
323 | |||
324 | /* paint the buffer blue */ | ||
325 | for (i = 0; i < width * height; i++) | ||
326 | fb_ptr[i] = 0xff; | ||
327 | |||
328 | ret = drmModeAddFB(fd, width, height, 32, 32, width * 4, bo->handle, | ||
329 | &fb_id); | ||
330 | if (ret) { | ||
331 | fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); | ||
332 | return; | ||
333 | } | ||
334 | |||
335 | ret = drmModeSetCrtc(fd, encoder->crtc_id, fb_id, 0, 0, | ||
336 | &connector->connector_id, 1, mode); | ||
337 | if (ret) { | ||
338 | fprintf(stderr, "failed to set mode: %s\n", strerror(errno)); | ||
339 | return; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | extern char *optarg; | ||
344 | extern int optind, opterr, optopt; | ||
345 | static char optstr[] = "ecpmfs:"; | ||
346 | |||
347 | void usage(char *name) | ||
348 | { | ||
349 | fprintf(stderr, "usage: %s [-ecpmf]\n", name); | ||
350 | fprintf(stderr, "\t-e\tlist encoders\n"); | ||
351 | fprintf(stderr, "\t-c\tlist connectors\n"); | ||
352 | fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n"); | ||
353 | fprintf(stderr, "\t-m\tlist modes\n"); | ||
354 | fprintf(stderr, "\t-f\tlist framebuffers\n"); | ||
355 | fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n"); | ||
356 | fprintf(stderr, "\n\tDefault is to dump all info.\n"); | ||
357 | exit(0); | ||
358 | } | ||
359 | |||
360 | #define dump_resource(res) if (res) dump_##res() | ||
361 | |||
362 | int main(int argc, char **argv) | ||
363 | { | ||
364 | int c; | ||
365 | int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0; | ||
366 | char *modules[] = { "i915", "radeon" }; | ||
367 | char *modeset = NULL, *mode, *connector; | ||
368 | int i, connector_id; | ||
369 | |||
370 | opterr = 0; | ||
371 | while ((c = getopt(argc, argv, optstr)) != -1) { | ||
372 | switch (c) { | ||
373 | case 'e': | ||
374 | encoders = 1; | ||
375 | break; | ||
376 | case 'c': | ||
377 | connectors = 1; | ||
378 | break; | ||
379 | case 'p': | ||
380 | crtcs = 1; | ||
381 | break; | ||
382 | case 'm': | ||
383 | modes = 1; | ||
384 | break; | ||
385 | case 'f': | ||
386 | framebuffers = 1; | ||
387 | break; | ||
388 | case 's': | ||
389 | modeset = strdup(optarg); | ||
390 | break; | ||
391 | default: | ||
392 | usage(argv[0]); | ||
393 | break; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | if (argc == 1) | ||
398 | encoders = connectors = crtcs = modes = framebuffers = 1; | ||
399 | |||
400 | for (i = 0; i < ARRAY_SIZE(modules); i++) { | ||
401 | printf("trying to load module %s...", modules[i]); | ||
402 | fd = drmOpen(modules[i], NULL); | ||
403 | if (fd < 0) { | ||
404 | printf("failed.\n"); | ||
405 | } else { | ||
406 | printf("success.\n"); | ||
407 | break; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | if (i == ARRAY_SIZE(modules)) { | ||
412 | fprintf(stderr, "failed to load any modules, aborting.\n"); | ||
413 | return -1; | ||
414 | } | ||
415 | |||
416 | resources = drmModeGetResources(fd); | ||
417 | if (!resources) { | ||
418 | fprintf(stderr, "drmModeGetResources failed: %s\n", | ||
419 | strerror(errno)); | ||
420 | drmClose(fd); | ||
421 | return 1; | ||
422 | } | ||
423 | |||
424 | dump_resource(encoders); | ||
425 | dump_resource(connectors); | ||
426 | dump_resource(crtcs); | ||
427 | dump_resource(framebuffers); | ||
428 | |||
429 | if (modeset) { | ||
430 | connector = strtok(modeset, ":"); | ||
431 | if (!connector) | ||
432 | usage(argv[0]); | ||
433 | connector_id = atoi(connector); | ||
434 | |||
435 | mode = strtok(NULL, ":"); | ||
436 | if (!mode) | ||
437 | usage(argv[0]); | ||
438 | printf("setting connector %d to mode %s\n", connector_id, | ||
439 | mode); | ||
440 | set_mode(connector_id, mode); | ||
441 | sleep(3); | ||
442 | } | ||
443 | |||
444 | sleep(3); | ||
445 | |||
446 | drmModeFreeResources(resources); | ||
447 | |||
448 | return 0; | ||
449 | } | ||
diff --git a/tests/modetest/test b/tests/modetest/test new file mode 100644 index 00000000..5bb552ef --- /dev/null +++ b/tests/modetest/test | |||
@@ -0,0 +1,2 @@ | |||
1 | export LD_LIBRARY_PATH=../../libdrm/.libs:../../libdrm/intel/.libs | ||
2 | LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@ | ||