xf86drmMode.c revision e05f3551
122944501Smrg/* 222944501Smrg * \file xf86drmMode.c 322944501Smrg * Header for DRM modesetting interface. 422944501Smrg * 522944501Smrg * \author Jakob Bornecrantz <wallbraker@gmail.com> 622944501Smrg * 722944501Smrg * \par Acknowledgements: 822944501Smrg * Feb 2007, Dave Airlie <airlied@linux.ie> 922944501Smrg */ 1022944501Smrg 1122944501Smrg/* 1222944501Smrg * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. 1322944501Smrg * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie> 1422944501Smrg * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> 1522944501Smrg * 1622944501Smrg * Permission is hereby granted, free of charge, to any person obtaining a 1722944501Smrg * copy of this software and associated documentation files (the "Software"), 1822944501Smrg * to deal in the Software without restriction, including without limitation 1922944501Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 2022944501Smrg * and/or sell copies of the Software, and to permit persons to whom the 2122944501Smrg * Software is furnished to do so, subject to the following conditions: 2222944501Smrg * 2322944501Smrg * The above copyright notice and this permission notice shall be included in 2422944501Smrg * all copies or substantial portions of the Software. 2522944501Smrg * 2622944501Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2722944501Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2822944501Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2922944501Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 3022944501Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 3122944501Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 3222944501Smrg * IN THE SOFTWARE. 3322944501Smrg * 3422944501Smrg */ 3522944501Smrg 3622944501Smrg/* 3722944501Smrg * TODO the types we are after are defined in diffrent headers on diffrent 3822944501Smrg * platforms find which headers to include to get uint32_t 3922944501Smrg */ 4022944501Smrg#include <stdint.h> 4122944501Smrg#include <sys/ioctl.h> 4222944501Smrg#include <stdio.h> 4322944501Smrg 44e88f27b3Smrg#ifdef HAVE_CONFIG_H 45e88f27b3Smrg#include "config.h" 46e88f27b3Smrg#endif 47e88f27b3Smrg 4822944501Smrg#include "xf86drmMode.h" 4922944501Smrg#include "xf86drm.h" 5022944501Smrg#include <drm.h> 5122944501Smrg#include <string.h> 5222944501Smrg#include <dirent.h> 5322944501Smrg#include <unistd.h> 5422944501Smrg#include <errno.h> 5522944501Smrg 56e88f27b3Smrg#ifdef HAVE_VALGRIND 57e88f27b3Smrg#include <valgrind.h> 58e88f27b3Smrg#include <memcheck.h> 59e88f27b3Smrg#define VG(x) x 60e88f27b3Smrg#else 61e88f27b3Smrg#define VG(x) 62e88f27b3Smrg#endif 63e88f27b3Smrg 64e88f27b3Smrg#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s))) 65e88f27b3Smrg 6622944501Smrg#define U642VOID(x) ((void *)(unsigned long)(x)) 6722944501Smrg#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) 6822944501Smrg 69e88f27b3Smrgstatic inline int DRM_IOCTL(int fd, unsigned long cmd, void *arg) 70d049871aSmrg{ 71d049871aSmrg int ret = drmIoctl(fd, cmd, arg); 72d049871aSmrg return ret < 0 ? -errno : ret; 73d049871aSmrg} 74d049871aSmrg 7522944501Smrg/* 7622944501Smrg * Util functions 7722944501Smrg */ 7822944501Smrg 7922944501Smrgvoid* drmAllocCpy(void *array, int count, int entry_size) 8022944501Smrg{ 8122944501Smrg char *r; 8222944501Smrg int i; 8322944501Smrg 8422944501Smrg if (!count || !array || !entry_size) 8522944501Smrg return 0; 8622944501Smrg 8722944501Smrg if (!(r = drmMalloc(count*entry_size))) 8822944501Smrg return 0; 8922944501Smrg 9022944501Smrg for (i = 0; i < count; i++) 9122944501Smrg memcpy(r+(entry_size*i), array+(entry_size*i), entry_size); 9222944501Smrg 9322944501Smrg return r; 9422944501Smrg} 9522944501Smrg 9622944501Smrg/* 9722944501Smrg * A couple of free functions. 9822944501Smrg */ 9922944501Smrg 10022944501Smrgvoid drmModeFreeModeInfo(drmModeModeInfoPtr ptr) 10122944501Smrg{ 10222944501Smrg if (!ptr) 10322944501Smrg return; 10422944501Smrg 10522944501Smrg drmFree(ptr); 10622944501Smrg} 10722944501Smrg 10822944501Smrgvoid drmModeFreeResources(drmModeResPtr ptr) 10922944501Smrg{ 11022944501Smrg if (!ptr) 11122944501Smrg return; 11222944501Smrg 113e88f27b3Smrg drmFree(ptr->fbs); 114e88f27b3Smrg drmFree(ptr->crtcs); 115e88f27b3Smrg drmFree(ptr->connectors); 116e88f27b3Smrg drmFree(ptr->encoders); 11722944501Smrg drmFree(ptr); 11822944501Smrg 11922944501Smrg} 12022944501Smrg 12122944501Smrgvoid drmModeFreeFB(drmModeFBPtr ptr) 12222944501Smrg{ 12322944501Smrg if (!ptr) 12422944501Smrg return; 12522944501Smrg 12622944501Smrg /* we might add more frees later. */ 12722944501Smrg drmFree(ptr); 12822944501Smrg} 12922944501Smrg 13022944501Smrgvoid drmModeFreeCrtc(drmModeCrtcPtr ptr) 13122944501Smrg{ 13222944501Smrg if (!ptr) 13322944501Smrg return; 13422944501Smrg 13522944501Smrg drmFree(ptr); 13622944501Smrg 13722944501Smrg} 13822944501Smrg 13922944501Smrgvoid drmModeFreeConnector(drmModeConnectorPtr ptr) 14022944501Smrg{ 14122944501Smrg if (!ptr) 14222944501Smrg return; 14322944501Smrg 14422944501Smrg drmFree(ptr->encoders); 14522944501Smrg drmFree(ptr->prop_values); 14622944501Smrg drmFree(ptr->props); 14722944501Smrg drmFree(ptr->modes); 14822944501Smrg drmFree(ptr); 14922944501Smrg 15022944501Smrg} 15122944501Smrg 15222944501Smrgvoid drmModeFreeEncoder(drmModeEncoderPtr ptr) 15322944501Smrg{ 15422944501Smrg drmFree(ptr); 15522944501Smrg} 15622944501Smrg 15722944501Smrg/* 15822944501Smrg * ModeSetting functions. 15922944501Smrg */ 16022944501Smrg 16122944501SmrgdrmModeResPtr drmModeGetResources(int fd) 16222944501Smrg{ 16322944501Smrg struct drm_mode_card_res res, counts; 16422944501Smrg drmModeResPtr r = 0; 16522944501Smrg 16622944501Smrgretry: 16722944501Smrg memset(&res, 0, sizeof(struct drm_mode_card_res)); 16822944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 16922944501Smrg return 0; 17022944501Smrg 17122944501Smrg counts = res; 17222944501Smrg 17322944501Smrg if (res.count_fbs) { 17422944501Smrg res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t))); 17522944501Smrg if (!res.fb_id_ptr) 17622944501Smrg goto err_allocs; 17722944501Smrg } 17822944501Smrg if (res.count_crtcs) { 17922944501Smrg res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t))); 18022944501Smrg if (!res.crtc_id_ptr) 18122944501Smrg goto err_allocs; 18222944501Smrg } 18322944501Smrg if (res.count_connectors) { 18422944501Smrg res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t))); 18522944501Smrg if (!res.connector_id_ptr) 18622944501Smrg goto err_allocs; 18722944501Smrg } 18822944501Smrg if (res.count_encoders) { 18922944501Smrg res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t))); 19022944501Smrg if (!res.encoder_id_ptr) 19122944501Smrg goto err_allocs; 19222944501Smrg } 19322944501Smrg 19422944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 19522944501Smrg goto err_allocs; 19622944501Smrg 19722944501Smrg /* The number of available connectors and etc may have changed with a 19822944501Smrg * hotplug event in between the ioctls, in which case the field is 19922944501Smrg * silently ignored by the kernel. 20022944501Smrg */ 20122944501Smrg if (counts.count_fbs < res.count_fbs || 20222944501Smrg counts.count_crtcs < res.count_crtcs || 20322944501Smrg counts.count_connectors < res.count_connectors || 20422944501Smrg counts.count_encoders < res.count_encoders) 20522944501Smrg { 20622944501Smrg drmFree(U642VOID(res.fb_id_ptr)); 20722944501Smrg drmFree(U642VOID(res.crtc_id_ptr)); 20822944501Smrg drmFree(U642VOID(res.connector_id_ptr)); 20922944501Smrg drmFree(U642VOID(res.encoder_id_ptr)); 21022944501Smrg 21122944501Smrg goto retry; 21222944501Smrg } 21322944501Smrg 21422944501Smrg /* 21522944501Smrg * return 21622944501Smrg */ 21722944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 21822944501Smrg goto err_allocs; 21922944501Smrg 22022944501Smrg r->min_width = res.min_width; 22122944501Smrg r->max_width = res.max_width; 22222944501Smrg r->min_height = res.min_height; 22322944501Smrg r->max_height = res.max_height; 22422944501Smrg r->count_fbs = res.count_fbs; 22522944501Smrg r->count_crtcs = res.count_crtcs; 22622944501Smrg r->count_connectors = res.count_connectors; 22722944501Smrg r->count_encoders = res.count_encoders; 22822944501Smrg 22922944501Smrg r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t)); 23022944501Smrg r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t)); 23122944501Smrg r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t)); 23222944501Smrg r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t)); 23322944501Smrg if ((res.count_fbs && !r->fbs) || 23422944501Smrg (res.count_crtcs && !r->crtcs) || 23522944501Smrg (res.count_connectors && !r->connectors) || 23622944501Smrg (res.count_encoders && !r->encoders)) 23722944501Smrg { 23822944501Smrg drmFree(r->fbs); 23922944501Smrg drmFree(r->crtcs); 24022944501Smrg drmFree(r->connectors); 24122944501Smrg drmFree(r->encoders); 24222944501Smrg drmFree(r); 24322944501Smrg r = 0; 24422944501Smrg } 24522944501Smrg 24622944501Smrgerr_allocs: 24722944501Smrg drmFree(U642VOID(res.fb_id_ptr)); 24822944501Smrg drmFree(U642VOID(res.crtc_id_ptr)); 24922944501Smrg drmFree(U642VOID(res.connector_id_ptr)); 25022944501Smrg drmFree(U642VOID(res.encoder_id_ptr)); 25122944501Smrg 25222944501Smrg return r; 25322944501Smrg} 25422944501Smrg 25522944501Smrgint drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, 25622944501Smrg uint8_t bpp, uint32_t pitch, uint32_t bo_handle, 25722944501Smrg uint32_t *buf_id) 25822944501Smrg{ 25922944501Smrg struct drm_mode_fb_cmd f; 26022944501Smrg int ret; 26122944501Smrg 262e88f27b3Smrg VG_CLEAR(f); 26322944501Smrg f.width = width; 26422944501Smrg f.height = height; 26522944501Smrg f.pitch = pitch; 26622944501Smrg f.bpp = bpp; 26722944501Smrg f.depth = depth; 26822944501Smrg f.handle = bo_handle; 26922944501Smrg 270d049871aSmrg if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f))) 27122944501Smrg return ret; 27222944501Smrg 27322944501Smrg *buf_id = f.fb_id; 27422944501Smrg return 0; 27522944501Smrg} 27622944501Smrg 277e88f27b3Smrgint drmModeAddFB2(int fd, uint32_t width, uint32_t height, 278e88f27b3Smrg uint32_t pixel_format, uint32_t bo_handles[4], 279e88f27b3Smrg uint32_t pitches[4], uint32_t offsets[4], 280e88f27b3Smrg uint32_t *buf_id, uint32_t flags) 281e88f27b3Smrg{ 282e88f27b3Smrg struct drm_mode_fb_cmd2 f; 283e88f27b3Smrg int ret; 284e88f27b3Smrg 285e88f27b3Smrg f.width = width; 286e88f27b3Smrg f.height = height; 287e88f27b3Smrg f.pixel_format = pixel_format; 288e88f27b3Smrg f.flags = flags; 289e88f27b3Smrg memcpy(f.handles, bo_handles, 4 * sizeof(bo_handles[0])); 290e88f27b3Smrg memcpy(f.pitches, pitches, 4 * sizeof(pitches[0])); 291e88f27b3Smrg memcpy(f.offsets, offsets, 4 * sizeof(offsets[0])); 292e88f27b3Smrg 293e88f27b3Smrg if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB2, &f))) 294e88f27b3Smrg return ret; 295e88f27b3Smrg 296e88f27b3Smrg *buf_id = f.fb_id; 297e88f27b3Smrg return 0; 298e88f27b3Smrg} 299e88f27b3Smrg 30022944501Smrgint drmModeRmFB(int fd, uint32_t bufferId) 30122944501Smrg{ 302d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); 30322944501Smrg 30422944501Smrg 30522944501Smrg} 30622944501Smrg 30722944501SmrgdrmModeFBPtr drmModeGetFB(int fd, uint32_t buf) 30822944501Smrg{ 30922944501Smrg struct drm_mode_fb_cmd info; 31022944501Smrg drmModeFBPtr r; 31122944501Smrg 31222944501Smrg info.fb_id = buf; 31322944501Smrg 31422944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info)) 31522944501Smrg return NULL; 31622944501Smrg 31722944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 31822944501Smrg return NULL; 31922944501Smrg 32022944501Smrg r->fb_id = info.fb_id; 32122944501Smrg r->width = info.width; 32222944501Smrg r->height = info.height; 32322944501Smrg r->pitch = info.pitch; 32422944501Smrg r->bpp = info.bpp; 32522944501Smrg r->handle = info.handle; 32622944501Smrg r->depth = info.depth; 32722944501Smrg 32822944501Smrg return r; 32922944501Smrg} 33022944501Smrg 33122944501Smrgint drmModeDirtyFB(int fd, uint32_t bufferId, 33222944501Smrg drmModeClipPtr clips, uint32_t num_clips) 33322944501Smrg{ 33422944501Smrg struct drm_mode_fb_dirty_cmd dirty = { 0 }; 33522944501Smrg 33622944501Smrg dirty.fb_id = bufferId; 33722944501Smrg dirty.clips_ptr = VOID2U64(clips); 33822944501Smrg dirty.num_clips = num_clips; 33922944501Smrg 340d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty); 34122944501Smrg} 34222944501Smrg 34322944501Smrg 34422944501Smrg/* 34522944501Smrg * Crtc functions 34622944501Smrg */ 34722944501Smrg 34822944501SmrgdrmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) 34922944501Smrg{ 35022944501Smrg struct drm_mode_crtc crtc; 35122944501Smrg drmModeCrtcPtr r; 35222944501Smrg 353e88f27b3Smrg VG_CLEAR(crtc); 35422944501Smrg crtc.crtc_id = crtcId; 35522944501Smrg 35622944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc)) 35722944501Smrg return 0; 35822944501Smrg 35922944501Smrg /* 36022944501Smrg * return 36122944501Smrg */ 36222944501Smrg 36322944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 36422944501Smrg return 0; 36522944501Smrg 36622944501Smrg r->crtc_id = crtc.crtc_id; 36722944501Smrg r->x = crtc.x; 36822944501Smrg r->y = crtc.y; 36922944501Smrg r->mode_valid = crtc.mode_valid; 370e88f27b3Smrg if (r->mode_valid) { 37122944501Smrg memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo)); 372e88f27b3Smrg r->width = crtc.mode.hdisplay; 373e88f27b3Smrg r->height = crtc.mode.vdisplay; 374e88f27b3Smrg } 37522944501Smrg r->buffer_id = crtc.fb_id; 37622944501Smrg r->gamma_size = crtc.gamma_size; 37722944501Smrg return r; 37822944501Smrg} 37922944501Smrg 38022944501Smrg 38122944501Smrgint drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, 38222944501Smrg uint32_t x, uint32_t y, uint32_t *connectors, int count, 38322944501Smrg drmModeModeInfoPtr mode) 38422944501Smrg{ 38522944501Smrg struct drm_mode_crtc crtc; 38622944501Smrg 387e88f27b3Smrg VG_CLEAR(crtc); 38822944501Smrg crtc.x = x; 38922944501Smrg crtc.y = y; 39022944501Smrg crtc.crtc_id = crtcId; 39122944501Smrg crtc.fb_id = bufferId; 39222944501Smrg crtc.set_connectors_ptr = VOID2U64(connectors); 39322944501Smrg crtc.count_connectors = count; 39422944501Smrg if (mode) { 39522944501Smrg memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo)); 39622944501Smrg crtc.mode_valid = 1; 39722944501Smrg } else 39822944501Smrg crtc.mode_valid = 0; 39922944501Smrg 400d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); 40122944501Smrg} 40222944501Smrg 40322944501Smrg/* 40422944501Smrg * Cursor manipulation 40522944501Smrg */ 40622944501Smrg 40722944501Smrgint drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height) 40822944501Smrg{ 40922944501Smrg struct drm_mode_cursor arg; 41022944501Smrg 41122944501Smrg arg.flags = DRM_MODE_CURSOR_BO; 41222944501Smrg arg.crtc_id = crtcId; 41322944501Smrg arg.width = width; 41422944501Smrg arg.height = height; 41522944501Smrg arg.handle = bo_handle; 41622944501Smrg 417d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 41822944501Smrg} 41922944501Smrg 420e88f27b3Smrgint drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y) 421e88f27b3Smrg{ 422e88f27b3Smrg struct drm_mode_cursor2 arg; 423e88f27b3Smrg 424e88f27b3Smrg arg.flags = DRM_MODE_CURSOR_BO; 425e88f27b3Smrg arg.crtc_id = crtcId; 426e88f27b3Smrg arg.width = width; 427e88f27b3Smrg arg.height = height; 428e88f27b3Smrg arg.handle = bo_handle; 429e88f27b3Smrg arg.hot_x = hot_x; 430e88f27b3Smrg arg.hot_y = hot_y; 431e88f27b3Smrg 432e88f27b3Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR2, &arg); 433e88f27b3Smrg} 434e88f27b3Smrg 43522944501Smrgint drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) 43622944501Smrg{ 43722944501Smrg struct drm_mode_cursor arg; 43822944501Smrg 43922944501Smrg arg.flags = DRM_MODE_CURSOR_MOVE; 44022944501Smrg arg.crtc_id = crtcId; 44122944501Smrg arg.x = x; 44222944501Smrg arg.y = y; 44322944501Smrg 444d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 44522944501Smrg} 44622944501Smrg 44722944501Smrg/* 44822944501Smrg * Encoder get 44922944501Smrg */ 45022944501SmrgdrmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) 45122944501Smrg{ 45222944501Smrg struct drm_mode_get_encoder enc; 45322944501Smrg drmModeEncoderPtr r = NULL; 45422944501Smrg 45522944501Smrg enc.encoder_id = encoder_id; 456e88f27b3Smrg enc.crtc_id = 0; 45722944501Smrg enc.encoder_type = 0; 45822944501Smrg enc.possible_crtcs = 0; 45922944501Smrg enc.possible_clones = 0; 46022944501Smrg 46122944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc)) 46222944501Smrg return 0; 46322944501Smrg 46422944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 46522944501Smrg return 0; 46622944501Smrg 46722944501Smrg r->encoder_id = enc.encoder_id; 46822944501Smrg r->crtc_id = enc.crtc_id; 46922944501Smrg r->encoder_type = enc.encoder_type; 47022944501Smrg r->possible_crtcs = enc.possible_crtcs; 47122944501Smrg r->possible_clones = enc.possible_clones; 47222944501Smrg 47322944501Smrg return r; 47422944501Smrg} 47522944501Smrg 47622944501Smrg/* 47722944501Smrg * Connector manipulation 47822944501Smrg */ 47922944501Smrg 48022944501SmrgdrmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) 48122944501Smrg{ 48222944501Smrg struct drm_mode_get_connector conn, counts; 48322944501Smrg drmModeConnectorPtr r = NULL; 48422944501Smrg 48522944501Smrgretry: 48622944501Smrg memset(&conn, 0, sizeof(struct drm_mode_get_connector)); 48722944501Smrg conn.connector_id = connector_id; 48822944501Smrg 48922944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 49022944501Smrg return 0; 49122944501Smrg 49222944501Smrg counts = conn; 49322944501Smrg 49422944501Smrg if (conn.count_props) { 49522944501Smrg conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t))); 49622944501Smrg if (!conn.props_ptr) 49722944501Smrg goto err_allocs; 49822944501Smrg conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t))); 49922944501Smrg if (!conn.prop_values_ptr) 50022944501Smrg goto err_allocs; 50122944501Smrg } 50222944501Smrg 50322944501Smrg if (conn.count_modes) { 50422944501Smrg conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); 50522944501Smrg if (!conn.modes_ptr) 50622944501Smrg goto err_allocs; 50722944501Smrg } 50822944501Smrg 50922944501Smrg if (conn.count_encoders) { 51022944501Smrg conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t))); 51122944501Smrg if (!conn.encoders_ptr) 51222944501Smrg goto err_allocs; 51322944501Smrg } 51422944501Smrg 51522944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 51622944501Smrg goto err_allocs; 51722944501Smrg 51822944501Smrg /* The number of available connectors and etc may have changed with a 51922944501Smrg * hotplug event in between the ioctls, in which case the field is 52022944501Smrg * silently ignored by the kernel. 52122944501Smrg */ 52222944501Smrg if (counts.count_props < conn.count_props || 52322944501Smrg counts.count_modes < conn.count_modes || 52422944501Smrg counts.count_encoders < conn.count_encoders) { 52522944501Smrg drmFree(U642VOID(conn.props_ptr)); 52622944501Smrg drmFree(U642VOID(conn.prop_values_ptr)); 52722944501Smrg drmFree(U642VOID(conn.modes_ptr)); 52822944501Smrg drmFree(U642VOID(conn.encoders_ptr)); 52922944501Smrg 53022944501Smrg goto retry; 53122944501Smrg } 53222944501Smrg 53322944501Smrg if(!(r = drmMalloc(sizeof(*r)))) { 53422944501Smrg goto err_allocs; 53522944501Smrg } 53622944501Smrg 53722944501Smrg r->connector_id = conn.connector_id; 53822944501Smrg r->encoder_id = conn.encoder_id; 53922944501Smrg r->connection = conn.connection; 54022944501Smrg r->mmWidth = conn.mm_width; 54122944501Smrg r->mmHeight = conn.mm_height; 54222944501Smrg /* convert subpixel from kernel to userspace */ 54322944501Smrg r->subpixel = conn.subpixel + 1; 54422944501Smrg r->count_modes = conn.count_modes; 54522944501Smrg r->count_props = conn.count_props; 54622944501Smrg r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t)); 54722944501Smrg r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t)); 54822944501Smrg r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo)); 54922944501Smrg r->count_encoders = conn.count_encoders; 55022944501Smrg r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t)); 55122944501Smrg r->connector_type = conn.connector_type; 55222944501Smrg r->connector_type_id = conn.connector_type_id; 55322944501Smrg 55422944501Smrg if ((r->count_props && !r->props) || 55522944501Smrg (r->count_props && !r->prop_values) || 55622944501Smrg (r->count_modes && !r->modes) || 55722944501Smrg (r->count_encoders && !r->encoders)) { 55822944501Smrg drmFree(r->props); 55922944501Smrg drmFree(r->prop_values); 56022944501Smrg drmFree(r->modes); 56122944501Smrg drmFree(r->encoders); 56222944501Smrg drmFree(r); 56322944501Smrg r = 0; 56422944501Smrg } 56522944501Smrg 56622944501Smrgerr_allocs: 56722944501Smrg drmFree(U642VOID(conn.prop_values_ptr)); 56822944501Smrg drmFree(U642VOID(conn.props_ptr)); 56922944501Smrg drmFree(U642VOID(conn.modes_ptr)); 57022944501Smrg drmFree(U642VOID(conn.encoders_ptr)); 57122944501Smrg 57222944501Smrg return r; 57322944501Smrg} 57422944501Smrg 57522944501Smrgint drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 57622944501Smrg{ 57722944501Smrg struct drm_mode_mode_cmd res; 57822944501Smrg 57922944501Smrg memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 58022944501Smrg res.connector_id = connector_id; 58122944501Smrg 582d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); 58322944501Smrg} 58422944501Smrg 58522944501Smrgint drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 58622944501Smrg{ 58722944501Smrg struct drm_mode_mode_cmd res; 58822944501Smrg 58922944501Smrg memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 59022944501Smrg res.connector_id = connector_id; 59122944501Smrg 592d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res); 59322944501Smrg} 59422944501Smrg 59522944501Smrg 59622944501SmrgdrmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) 59722944501Smrg{ 59822944501Smrg struct drm_mode_get_property prop; 59922944501Smrg drmModePropertyPtr r; 60022944501Smrg 601e88f27b3Smrg VG_CLEAR(prop); 60222944501Smrg prop.prop_id = property_id; 60322944501Smrg prop.count_enum_blobs = 0; 60422944501Smrg prop.count_values = 0; 60522944501Smrg prop.flags = 0; 60622944501Smrg prop.enum_blob_ptr = 0; 60722944501Smrg prop.values_ptr = 0; 60822944501Smrg 60922944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) 61022944501Smrg return 0; 61122944501Smrg 61222944501Smrg if (prop.count_values) 61322944501Smrg prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t))); 61422944501Smrg 615e88f27b3Smrg if (prop.count_enum_blobs && (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) 61622944501Smrg prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum))); 61722944501Smrg 61822944501Smrg if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) { 61922944501Smrg prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 62022944501Smrg prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 62122944501Smrg } 62222944501Smrg 62322944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) { 62422944501Smrg r = NULL; 62522944501Smrg goto err_allocs; 62622944501Smrg } 62722944501Smrg 62822944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 62922944501Smrg return NULL; 63022944501Smrg 63122944501Smrg r->prop_id = prop.prop_id; 63222944501Smrg r->count_values = prop.count_values; 63322944501Smrg 63422944501Smrg r->flags = prop.flags; 63522944501Smrg if (prop.count_values) 63622944501Smrg r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t)); 637e88f27b3Smrg if (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { 63822944501Smrg r->count_enums = prop.count_enum_blobs; 63922944501Smrg r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); 64022944501Smrg } else if (prop.flags & DRM_MODE_PROP_BLOB) { 64122944501Smrg r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 64222944501Smrg r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 64322944501Smrg r->count_blobs = prop.count_enum_blobs; 64422944501Smrg } 64522944501Smrg strncpy(r->name, prop.name, DRM_PROP_NAME_LEN); 64622944501Smrg r->name[DRM_PROP_NAME_LEN-1] = 0; 64722944501Smrg 64822944501Smrgerr_allocs: 64922944501Smrg drmFree(U642VOID(prop.values_ptr)); 65022944501Smrg drmFree(U642VOID(prop.enum_blob_ptr)); 65122944501Smrg 65222944501Smrg return r; 65322944501Smrg} 65422944501Smrg 65522944501Smrgvoid drmModeFreeProperty(drmModePropertyPtr ptr) 65622944501Smrg{ 65722944501Smrg if (!ptr) 65822944501Smrg return; 65922944501Smrg 66022944501Smrg drmFree(ptr->values); 66122944501Smrg drmFree(ptr->enums); 66222944501Smrg drmFree(ptr); 66322944501Smrg} 66422944501Smrg 66522944501SmrgdrmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id) 66622944501Smrg{ 66722944501Smrg struct drm_mode_get_blob blob; 66822944501Smrg drmModePropertyBlobPtr r; 66922944501Smrg 67022944501Smrg blob.length = 0; 67122944501Smrg blob.data = 0; 67222944501Smrg blob.blob_id = blob_id; 67322944501Smrg 67422944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) 67522944501Smrg return NULL; 67622944501Smrg 67722944501Smrg if (blob.length) 67822944501Smrg blob.data = VOID2U64(drmMalloc(blob.length)); 67922944501Smrg 68022944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) { 68122944501Smrg r = NULL; 68222944501Smrg goto err_allocs; 68322944501Smrg } 68422944501Smrg 68522944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 686d049871aSmrg goto err_allocs; 68722944501Smrg 68822944501Smrg r->id = blob.blob_id; 68922944501Smrg r->length = blob.length; 69022944501Smrg r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length); 69122944501Smrg 69222944501Smrgerr_allocs: 69322944501Smrg drmFree(U642VOID(blob.data)); 69422944501Smrg return r; 69522944501Smrg} 69622944501Smrg 69722944501Smrgvoid drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) 69822944501Smrg{ 69922944501Smrg if (!ptr) 70022944501Smrg return; 70122944501Smrg 70222944501Smrg drmFree(ptr->data); 70322944501Smrg drmFree(ptr); 70422944501Smrg} 70522944501Smrg 70622944501Smrgint drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, 70722944501Smrg uint64_t value) 70822944501Smrg{ 70922944501Smrg struct drm_mode_connector_set_property osp; 71022944501Smrg 71122944501Smrg osp.connector_id = connector_id; 71222944501Smrg osp.prop_id = property_id; 71322944501Smrg osp.value = value; 71422944501Smrg 715d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp); 71622944501Smrg} 71722944501Smrg 71822944501Smrg/* 71922944501Smrg * checks if a modesetting capable driver has attached to the pci id 72022944501Smrg * returns 0 if modesetting supported. 72122944501Smrg * -EINVAL or invalid bus id 72222944501Smrg * -ENOSYS if no modesetting support 72322944501Smrg*/ 72422944501Smrgint drmCheckModesettingSupported(const char *busid) 72522944501Smrg{ 726a7d7de1eSmrg#if defined (__linux__) 72722944501Smrg char pci_dev_dir[1024]; 72822944501Smrg int domain, bus, dev, func; 72922944501Smrg DIR *sysdir; 73022944501Smrg struct dirent *dent; 73122944501Smrg int found = 0, ret; 73222944501Smrg 73322944501Smrg ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); 73422944501Smrg if (ret != 4) 73522944501Smrg return -EINVAL; 73622944501Smrg 73722944501Smrg sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm", 73822944501Smrg domain, bus, dev, func); 73922944501Smrg 74022944501Smrg sysdir = opendir(pci_dev_dir); 74122944501Smrg if (sysdir) { 74222944501Smrg dent = readdir(sysdir); 74322944501Smrg while (dent) { 74422944501Smrg if (!strncmp(dent->d_name, "controlD", 8)) { 74522944501Smrg found = 1; 74622944501Smrg break; 74722944501Smrg } 74822944501Smrg 74922944501Smrg dent = readdir(sysdir); 75022944501Smrg } 75122944501Smrg closedir(sysdir); 75222944501Smrg if (found) 75322944501Smrg return 0; 75422944501Smrg } 75522944501Smrg 75622944501Smrg sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/", 75722944501Smrg domain, bus, dev, func); 75822944501Smrg 75922944501Smrg sysdir = opendir(pci_dev_dir); 76022944501Smrg if (!sysdir) 76122944501Smrg return -EINVAL; 76222944501Smrg 76322944501Smrg dent = readdir(sysdir); 76422944501Smrg while (dent) { 76522944501Smrg if (!strncmp(dent->d_name, "drm:controlD", 12)) { 76622944501Smrg found = 1; 76722944501Smrg break; 76822944501Smrg } 76922944501Smrg 77022944501Smrg dent = readdir(sysdir); 77122944501Smrg } 77222944501Smrg 77322944501Smrg closedir(sysdir); 77422944501Smrg if (found) 77522944501Smrg return 0; 776a7d7de1eSmrg#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) 777a7d7de1eSmrg char kbusid[1024], sbusid[1024]; 778a7d7de1eSmrg char oid[128]; 779a7d7de1eSmrg int domain, bus, dev, func; 780a7d7de1eSmrg int i, modesetting, ret; 781a7d7de1eSmrg size_t len; 782a7d7de1eSmrg 783a7d7de1eSmrg ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, 784a7d7de1eSmrg &func); 785a7d7de1eSmrg if (ret != 4) 786a7d7de1eSmrg return -EINVAL; 787a7d7de1eSmrg snprintf(kbusid, sizeof(kbusid), "pci:%04x:%02x:%02x.%d", domain, bus, 788a7d7de1eSmrg dev, func); 789a7d7de1eSmrg 790a7d7de1eSmrg /* How many GPUs do we expect in the machine ? */ 791a7d7de1eSmrg for (i = 0; i < 16; i++) { 792a7d7de1eSmrg snprintf(oid, sizeof(oid), "hw.dri.%d.busid", i); 793a7d7de1eSmrg len = sizeof(sbusid); 794a7d7de1eSmrg ret = sysctlbyname(oid, sbusid, &len, NULL, 0); 795a7d7de1eSmrg if (ret == -1) { 796a7d7de1eSmrg if (errno == ENOENT) 797a7d7de1eSmrg continue; 798a7d7de1eSmrg return -EINVAL; 799a7d7de1eSmrg } 800a7d7de1eSmrg if (strcmp(sbusid, kbusid) != 0) 801a7d7de1eSmrg continue; 802a7d7de1eSmrg snprintf(oid, sizeof(oid), "hw.dri.%d.modesetting", i); 803a7d7de1eSmrg len = sizeof(modesetting); 804a7d7de1eSmrg ret = sysctlbyname(oid, &modesetting, &len, NULL, 0); 805a7d7de1eSmrg if (ret == -1 || len != sizeof(modesetting)) 806a7d7de1eSmrg return -EINVAL; 807a7d7de1eSmrg return (modesetting ? 0 : -ENOSYS); 808a7d7de1eSmrg } 809e05f3551Smrg#elif defined(__DragonFly__) 810e05f3551Smrg return 0; 811d485a2c2Sriastradh#else 8127811b380Sriastradh int fd; 8137811b380Sriastradh static const struct drm_mode_card_res zero_res; 8147811b380Sriastradh struct drm_mode_card_res res = zero_res; 8157811b380Sriastradh int ret; 816a7d7de1eSmrg 8177811b380Sriastradh fd = drmOpen(NULL, busid); 8187811b380Sriastradh if (fd == -1) 8197811b380Sriastradh return -EINVAL; 8207d13a5d0Sriastradh ret = drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res); 8217811b380Sriastradh drmClose(fd); 8227d13a5d0Sriastradh if (ret == 0) 8237d13a5d0Sriastradh return 0; 8247811b380Sriastradh#endif 8257d13a5d0Sriastradh return -ENOSYS; 8267d13a5d0Sriastradh 82722944501Smrg} 82822944501Smrg 82922944501Smrgint drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, 83022944501Smrg uint16_t *red, uint16_t *green, uint16_t *blue) 83122944501Smrg{ 83222944501Smrg struct drm_mode_crtc_lut l; 83322944501Smrg 83422944501Smrg l.crtc_id = crtc_id; 83522944501Smrg l.gamma_size = size; 83622944501Smrg l.red = VOID2U64(red); 83722944501Smrg l.green = VOID2U64(green); 83822944501Smrg l.blue = VOID2U64(blue); 83922944501Smrg 840d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l); 84122944501Smrg} 84222944501Smrg 84322944501Smrgint drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, 84422944501Smrg uint16_t *red, uint16_t *green, uint16_t *blue) 84522944501Smrg{ 84622944501Smrg struct drm_mode_crtc_lut l; 84722944501Smrg 84822944501Smrg l.crtc_id = crtc_id; 84922944501Smrg l.gamma_size = size; 85022944501Smrg l.red = VOID2U64(red); 85122944501Smrg l.green = VOID2U64(green); 85222944501Smrg l.blue = VOID2U64(blue); 85322944501Smrg 854d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l); 85522944501Smrg} 85622944501Smrg 85722944501Smrgint drmHandleEvent(int fd, drmEventContextPtr evctx) 85822944501Smrg{ 85922944501Smrg char buffer[1024]; 86022944501Smrg int len, i; 86122944501Smrg struct drm_event *e; 86222944501Smrg struct drm_event_vblank *vblank; 86322944501Smrg 86422944501Smrg /* The DRM read semantics guarantees that we always get only 86522944501Smrg * complete events. */ 86622944501Smrg 86722944501Smrg len = read(fd, buffer, sizeof buffer); 86822944501Smrg if (len == 0) 86922944501Smrg return 0; 87022944501Smrg if (len < sizeof *e) 87122944501Smrg return -1; 87222944501Smrg 87322944501Smrg i = 0; 87422944501Smrg while (i < len) { 87522944501Smrg e = (struct drm_event *) &buffer[i]; 87622944501Smrg switch (e->type) { 87722944501Smrg case DRM_EVENT_VBLANK: 87822944501Smrg if (evctx->version < 1 || 87922944501Smrg evctx->vblank_handler == NULL) 88022944501Smrg break; 88122944501Smrg vblank = (struct drm_event_vblank *) e; 88222944501Smrg evctx->vblank_handler(fd, 88322944501Smrg vblank->sequence, 88422944501Smrg vblank->tv_sec, 88522944501Smrg vblank->tv_usec, 88622944501Smrg U642VOID (vblank->user_data)); 88722944501Smrg break; 88822944501Smrg case DRM_EVENT_FLIP_COMPLETE: 88922944501Smrg if (evctx->version < 2 || 89022944501Smrg evctx->page_flip_handler == NULL) 89122944501Smrg break; 89222944501Smrg vblank = (struct drm_event_vblank *) e; 89322944501Smrg evctx->page_flip_handler(fd, 89422944501Smrg vblank->sequence, 89522944501Smrg vblank->tv_sec, 89622944501Smrg vblank->tv_usec, 89722944501Smrg U642VOID (vblank->user_data)); 89822944501Smrg break; 89922944501Smrg default: 90022944501Smrg break; 90122944501Smrg } 90222944501Smrg i += e->length; 90322944501Smrg } 90422944501Smrg 90522944501Smrg return 0; 90622944501Smrg} 90722944501Smrg 90822944501Smrgint drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, 90922944501Smrg uint32_t flags, void *user_data) 91022944501Smrg{ 91122944501Smrg struct drm_mode_crtc_page_flip flip; 91222944501Smrg 91322944501Smrg flip.fb_id = fb_id; 91422944501Smrg flip.crtc_id = crtc_id; 91522944501Smrg flip.user_data = VOID2U64(user_data); 91622944501Smrg flip.flags = flags; 91722944501Smrg flip.reserved = 0; 91822944501Smrg 919d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); 92022944501Smrg} 921e88f27b3Smrg 922e88f27b3Smrgint drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, 923e88f27b3Smrg uint32_t fb_id, uint32_t flags, 924becaf760Smrg uint32_t crtc_x, uint32_t crtc_y, 925e88f27b3Smrg uint32_t crtc_w, uint32_t crtc_h, 926e88f27b3Smrg uint32_t src_x, uint32_t src_y, 927e88f27b3Smrg uint32_t src_w, uint32_t src_h) 928e88f27b3Smrg 929e88f27b3Smrg{ 930e88f27b3Smrg struct drm_mode_set_plane s; 931e88f27b3Smrg 932e88f27b3Smrg s.plane_id = plane_id; 933e88f27b3Smrg s.crtc_id = crtc_id; 934e88f27b3Smrg s.fb_id = fb_id; 935e88f27b3Smrg s.flags = flags; 936e88f27b3Smrg s.crtc_x = crtc_x; 937e88f27b3Smrg s.crtc_y = crtc_y; 938e88f27b3Smrg s.crtc_w = crtc_w; 939e88f27b3Smrg s.crtc_h = crtc_h; 940e88f27b3Smrg s.src_x = src_x; 941e88f27b3Smrg s.src_y = src_y; 942e88f27b3Smrg s.src_w = src_w; 943e88f27b3Smrg s.src_h = src_h; 944e88f27b3Smrg 945e88f27b3Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s); 946e88f27b3Smrg} 947e88f27b3Smrg 948e88f27b3Smrg 949e88f27b3SmrgdrmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) 950e88f27b3Smrg{ 951e88f27b3Smrg struct drm_mode_get_plane ovr, counts; 952e88f27b3Smrg drmModePlanePtr r = 0; 953e88f27b3Smrg 954e88f27b3Smrgretry: 955e88f27b3Smrg memset(&ovr, 0, sizeof(struct drm_mode_get_plane)); 956e88f27b3Smrg ovr.plane_id = plane_id; 957e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) 958e88f27b3Smrg return 0; 959e88f27b3Smrg 960e88f27b3Smrg counts = ovr; 961e88f27b3Smrg 962e88f27b3Smrg if (ovr.count_format_types) { 963e88f27b3Smrg ovr.format_type_ptr = VOID2U64(drmMalloc(ovr.count_format_types * 964e88f27b3Smrg sizeof(uint32_t))); 965e88f27b3Smrg if (!ovr.format_type_ptr) 966e88f27b3Smrg goto err_allocs; 967e88f27b3Smrg } 968e88f27b3Smrg 969e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) 970e88f27b3Smrg goto err_allocs; 971e88f27b3Smrg 972e88f27b3Smrg if (counts.count_format_types < ovr.count_format_types) { 973e88f27b3Smrg drmFree(U642VOID(ovr.format_type_ptr)); 974e88f27b3Smrg goto retry; 975e88f27b3Smrg } 976e88f27b3Smrg 977e88f27b3Smrg if (!(r = drmMalloc(sizeof(*r)))) 978e88f27b3Smrg goto err_allocs; 979e88f27b3Smrg 980e88f27b3Smrg r->count_formats = ovr.count_format_types; 981e88f27b3Smrg r->plane_id = ovr.plane_id; 982e88f27b3Smrg r->crtc_id = ovr.crtc_id; 983e88f27b3Smrg r->fb_id = ovr.fb_id; 984e88f27b3Smrg r->possible_crtcs = ovr.possible_crtcs; 985e88f27b3Smrg r->gamma_size = ovr.gamma_size; 986e88f27b3Smrg r->formats = drmAllocCpy(U642VOID(ovr.format_type_ptr), 987e88f27b3Smrg ovr.count_format_types, sizeof(uint32_t)); 988e88f27b3Smrg if (ovr.count_format_types && !r->formats) { 989e88f27b3Smrg drmFree(r->formats); 990e88f27b3Smrg drmFree(r); 991e88f27b3Smrg r = 0; 992e88f27b3Smrg } 993e88f27b3Smrg 994e88f27b3Smrgerr_allocs: 995e88f27b3Smrg drmFree(U642VOID(ovr.format_type_ptr)); 996e88f27b3Smrg 997e88f27b3Smrg return r; 998e88f27b3Smrg} 999e88f27b3Smrg 1000e88f27b3Smrgvoid drmModeFreePlane(drmModePlanePtr ptr) 1001e88f27b3Smrg{ 1002e88f27b3Smrg if (!ptr) 1003e88f27b3Smrg return; 1004e88f27b3Smrg 1005e88f27b3Smrg drmFree(ptr->formats); 1006e88f27b3Smrg drmFree(ptr); 1007e88f27b3Smrg} 1008e88f27b3Smrg 1009e88f27b3SmrgdrmModePlaneResPtr drmModeGetPlaneResources(int fd) 1010e88f27b3Smrg{ 1011e88f27b3Smrg struct drm_mode_get_plane_res res, counts; 1012e88f27b3Smrg drmModePlaneResPtr r = 0; 1013e88f27b3Smrg 1014e88f27b3Smrgretry: 1015e88f27b3Smrg memset(&res, 0, sizeof(struct drm_mode_get_plane_res)); 1016e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) 1017e88f27b3Smrg return 0; 1018e88f27b3Smrg 1019e88f27b3Smrg counts = res; 1020e88f27b3Smrg 1021e88f27b3Smrg if (res.count_planes) { 1022e88f27b3Smrg res.plane_id_ptr = VOID2U64(drmMalloc(res.count_planes * 1023e88f27b3Smrg sizeof(uint32_t))); 1024e88f27b3Smrg if (!res.plane_id_ptr) 1025e88f27b3Smrg goto err_allocs; 1026e88f27b3Smrg } 1027e88f27b3Smrg 1028e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) 1029e88f27b3Smrg goto err_allocs; 1030e88f27b3Smrg 1031e88f27b3Smrg if (counts.count_planes < res.count_planes) { 1032e88f27b3Smrg drmFree(U642VOID(res.plane_id_ptr)); 1033e88f27b3Smrg goto retry; 1034e88f27b3Smrg } 1035e88f27b3Smrg 1036e88f27b3Smrg if (!(r = drmMalloc(sizeof(*r)))) 1037e88f27b3Smrg goto err_allocs; 1038e88f27b3Smrg 1039e88f27b3Smrg r->count_planes = res.count_planes; 1040e88f27b3Smrg r->planes = drmAllocCpy(U642VOID(res.plane_id_ptr), 1041e88f27b3Smrg res.count_planes, sizeof(uint32_t)); 1042e88f27b3Smrg if (res.count_planes && !r->planes) { 1043e88f27b3Smrg drmFree(r->planes); 1044e88f27b3Smrg drmFree(r); 1045e88f27b3Smrg r = 0; 1046e88f27b3Smrg } 1047e88f27b3Smrg 1048e88f27b3Smrgerr_allocs: 1049e88f27b3Smrg drmFree(U642VOID(res.plane_id_ptr)); 1050e88f27b3Smrg 1051e88f27b3Smrg return r; 1052e88f27b3Smrg} 1053e88f27b3Smrg 1054e88f27b3Smrgvoid drmModeFreePlaneResources(drmModePlaneResPtr ptr) 1055e88f27b3Smrg{ 1056e88f27b3Smrg if (!ptr) 1057e88f27b3Smrg return; 1058e88f27b3Smrg 1059e88f27b3Smrg drmFree(ptr->planes); 1060e88f27b3Smrg drmFree(ptr); 1061e88f27b3Smrg} 1062e88f27b3Smrg 1063e88f27b3SmrgdrmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, 1064e88f27b3Smrg uint32_t object_id, 1065e88f27b3Smrg uint32_t object_type) 1066e88f27b3Smrg{ 1067e88f27b3Smrg struct drm_mode_obj_get_properties properties; 1068e88f27b3Smrg drmModeObjectPropertiesPtr ret = NULL; 1069e88f27b3Smrg uint32_t count; 1070e88f27b3Smrg 1071e88f27b3Smrgretry: 1072e88f27b3Smrg memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties)); 1073e88f27b3Smrg properties.obj_id = object_id; 1074e88f27b3Smrg properties.obj_type = object_type; 1075e88f27b3Smrg 1076e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) 1077e88f27b3Smrg return 0; 1078e88f27b3Smrg 1079e88f27b3Smrg count = properties.count_props; 1080e88f27b3Smrg 1081e88f27b3Smrg if (count) { 1082e88f27b3Smrg properties.props_ptr = VOID2U64(drmMalloc(count * 1083e88f27b3Smrg sizeof(uint32_t))); 1084e88f27b3Smrg if (!properties.props_ptr) 1085e88f27b3Smrg goto err_allocs; 1086e88f27b3Smrg properties.prop_values_ptr = VOID2U64(drmMalloc(count * 1087e88f27b3Smrg sizeof(uint64_t))); 1088e88f27b3Smrg if (!properties.prop_values_ptr) 1089e88f27b3Smrg goto err_allocs; 1090e88f27b3Smrg } 1091e88f27b3Smrg 1092e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) 1093e88f27b3Smrg goto err_allocs; 1094e88f27b3Smrg 1095e88f27b3Smrg if (count < properties.count_props) { 1096e88f27b3Smrg drmFree(U642VOID(properties.props_ptr)); 1097e88f27b3Smrg drmFree(U642VOID(properties.prop_values_ptr)); 1098e88f27b3Smrg goto retry; 1099e88f27b3Smrg } 1100e88f27b3Smrg count = properties.count_props; 1101e88f27b3Smrg 1102e88f27b3Smrg ret = drmMalloc(sizeof(*ret)); 1103e88f27b3Smrg if (!ret) 1104e88f27b3Smrg goto err_allocs; 1105e88f27b3Smrg 1106e88f27b3Smrg ret->count_props = count; 1107e88f27b3Smrg ret->props = drmAllocCpy(U642VOID(properties.props_ptr), 1108e88f27b3Smrg count, sizeof(uint32_t)); 1109e88f27b3Smrg ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr), 1110e88f27b3Smrg count, sizeof(uint64_t)); 1111e88f27b3Smrg if (ret->count_props && (!ret->props || !ret->prop_values)) { 1112e88f27b3Smrg drmFree(ret->props); 1113e88f27b3Smrg drmFree(ret->prop_values); 1114e88f27b3Smrg drmFree(ret); 1115e88f27b3Smrg ret = NULL; 1116e88f27b3Smrg } 1117e88f27b3Smrg 1118e88f27b3Smrgerr_allocs: 1119e88f27b3Smrg drmFree(U642VOID(properties.props_ptr)); 1120e88f27b3Smrg drmFree(U642VOID(properties.prop_values_ptr)); 1121e88f27b3Smrg return ret; 1122e88f27b3Smrg} 1123e88f27b3Smrg 1124e88f27b3Smrgvoid drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr) 1125e88f27b3Smrg{ 1126e88f27b3Smrg if (!ptr) 1127e88f27b3Smrg return; 1128e88f27b3Smrg drmFree(ptr->props); 1129e88f27b3Smrg drmFree(ptr->prop_values); 1130e88f27b3Smrg drmFree(ptr); 1131e88f27b3Smrg} 1132e88f27b3Smrg 1133e88f27b3Smrgint drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, 1134e88f27b3Smrg uint32_t property_id, uint64_t value) 1135e88f27b3Smrg{ 1136e88f27b3Smrg struct drm_mode_obj_set_property prop; 1137e88f27b3Smrg 1138e88f27b3Smrg prop.value = value; 1139e88f27b3Smrg prop.prop_id = property_id; 1140e88f27b3Smrg prop.obj_id = object_id; 1141e88f27b3Smrg prop.obj_type = object_type; 1142e88f27b3Smrg 1143e88f27b3Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); 1144e88f27b3Smrg} 1145