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.main
parent
c86d431fe6
commit
731cd5526e
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -0,0 +1 @@
|
|||
../shared-core/drm_mode.h
|
|
@ -25,6 +25,7 @@
|
|||
klibdrmincludedir = ${includedir}/drm
|
||||
klibdrminclude_HEADERS = \
|
||||
drm.h \
|
||||
drm_mode.h \
|
||||
drm_sarea.h \
|
||||
i915_drm.h \
|
||||
mach64_drm.h \
|
||||
|
|
|
@ -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)
|
||||
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
|
@ -15,6 +15,10 @@ libdrmtest_la_LIBADD = \
|
|||
|
||||
LDADD = libdrmtest.la
|
||||
|
||||
noinst_SUBDIRS = \
|
||||
modeprint \
|
||||
modetest
|
||||
|
||||
TESTS = auth \
|
||||
openclose \
|
||||
getversion \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
Binary file not shown.
|
@ -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;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export LD_LIBRARY_PATH=../../libdrm/.libs:../../libdrm/intel/.libs
|
||||
LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@
|
Loading…
Reference in New Issue