xf86drmMode.c revision 48246ce7
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 36adfa0b0cSmrg#include <assert.h> 37424e9256Smrg#include <limits.h> 38424e9256Smrg#include <stdint.h> 39424e9256Smrg#include <stdlib.h> 40424e9256Smrg#include <sys/ioctl.h> 4187bf8e7cSmrg#if HAVE_SYS_SYSCTL_H 42636d5e9fSmrg#ifdef __FreeBSD__ 43636d5e9fSmrg#include <sys/types.h> 44636d5e9fSmrg#endif 45fe517fc9Smrg#include <sys/sysctl.h> 46fe517fc9Smrg#endif 47424e9256Smrg#include <stdio.h> 48424e9256Smrg#include <stdbool.h> 49424e9256Smrg 506260e5d5Smrg#include "libdrm_macros.h" 5122944501Smrg#include "xf86drmMode.h" 5222944501Smrg#include "xf86drm.h" 5322944501Smrg#include <drm.h> 54adfa0b0cSmrg#include <drm_fourcc.h> 5522944501Smrg#include <string.h> 5622944501Smrg#include <dirent.h> 5722944501Smrg#include <unistd.h> 5822944501Smrg#include <errno.h> 5922944501Smrg 60424e9256Smrg#define memclear(s) memset(&s, 0, sizeof(s)) 61e88f27b3Smrg 6222944501Smrg#define U642VOID(x) ((void *)(unsigned long)(x)) 6322944501Smrg#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) 6422944501Smrg 65e88f27b3Smrgstatic inline int DRM_IOCTL(int fd, unsigned long cmd, void *arg) 66d049871aSmrg{ 67d049871aSmrg int ret = drmIoctl(fd, cmd, arg); 68d049871aSmrg return ret < 0 ? -errno : ret; 69d049871aSmrg} 70d049871aSmrg 7122944501Smrg/* 7222944501Smrg * Util functions 7322944501Smrg */ 7422944501Smrg 75424e9256Smrgstatic void* drmAllocCpy(char *array, int count, int entry_size) 7622944501Smrg{ 7722944501Smrg char *r; 7822944501Smrg int i; 7922944501Smrg 8022944501Smrg if (!count || !array || !entry_size) 8122944501Smrg return 0; 8222944501Smrg 8322944501Smrg if (!(r = drmMalloc(count*entry_size))) 8422944501Smrg return 0; 8522944501Smrg 8622944501Smrg for (i = 0; i < count; i++) 8722944501Smrg memcpy(r+(entry_size*i), array+(entry_size*i), entry_size); 8822944501Smrg 8922944501Smrg return r; 9022944501Smrg} 9122944501Smrg 9222944501Smrg/* 9322944501Smrg * A couple of free functions. 9422944501Smrg */ 9522944501Smrg 966260e5d5Smrgdrm_public void drmModeFreeModeInfo(drmModeModeInfoPtr ptr) 9722944501Smrg{ 9822944501Smrg if (!ptr) 9922944501Smrg return; 10022944501Smrg 10122944501Smrg drmFree(ptr); 10222944501Smrg} 10322944501Smrg 1046260e5d5Smrgdrm_public void drmModeFreeResources(drmModeResPtr ptr) 10522944501Smrg{ 10622944501Smrg if (!ptr) 10722944501Smrg return; 10822944501Smrg 109e88f27b3Smrg drmFree(ptr->fbs); 110e88f27b3Smrg drmFree(ptr->crtcs); 111e88f27b3Smrg drmFree(ptr->connectors); 112e88f27b3Smrg drmFree(ptr->encoders); 11322944501Smrg drmFree(ptr); 11422944501Smrg} 11522944501Smrg 1166260e5d5Smrgdrm_public void drmModeFreeFB(drmModeFBPtr ptr) 11722944501Smrg{ 11822944501Smrg if (!ptr) 11922944501Smrg return; 12022944501Smrg 12122944501Smrg /* we might add more frees later. */ 12222944501Smrg drmFree(ptr); 12322944501Smrg} 12422944501Smrg 1256260e5d5Smrgdrm_public void drmModeFreeCrtc(drmModeCrtcPtr ptr) 12622944501Smrg{ 12722944501Smrg if (!ptr) 12822944501Smrg return; 12922944501Smrg 13022944501Smrg drmFree(ptr); 13122944501Smrg} 13222944501Smrg 1336260e5d5Smrgdrm_public void drmModeFreeConnector(drmModeConnectorPtr ptr) 13422944501Smrg{ 13522944501Smrg if (!ptr) 13622944501Smrg return; 13722944501Smrg 13822944501Smrg drmFree(ptr->encoders); 13922944501Smrg drmFree(ptr->prop_values); 14022944501Smrg drmFree(ptr->props); 14122944501Smrg drmFree(ptr->modes); 14222944501Smrg drmFree(ptr); 14322944501Smrg} 14422944501Smrg 1456260e5d5Smrgdrm_public void drmModeFreeEncoder(drmModeEncoderPtr ptr) 14622944501Smrg{ 14722944501Smrg drmFree(ptr); 14822944501Smrg} 14922944501Smrg 15022944501Smrg/* 15122944501Smrg * ModeSetting functions. 15222944501Smrg */ 15322944501Smrg 1544b3d3f37Smrgdrm_public int drmIsKMS(int fd) 1554b3d3f37Smrg{ 1564b3d3f37Smrg struct drm_mode_card_res res = {0}; 1574b3d3f37Smrg 1584b3d3f37Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res) != 0) 1594b3d3f37Smrg return 0; 1604b3d3f37Smrg 1614b3d3f37Smrg return res.count_crtcs > 0 && res.count_connectors > 0 && res.count_encoders > 0; 1624b3d3f37Smrg} 1634b3d3f37Smrg 1646260e5d5Smrgdrm_public drmModeResPtr drmModeGetResources(int fd) 16522944501Smrg{ 16622944501Smrg struct drm_mode_card_res res, counts; 16722944501Smrg drmModeResPtr r = 0; 16822944501Smrg 16922944501Smrgretry: 170424e9256Smrg memclear(res); 17122944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 17222944501Smrg return 0; 17322944501Smrg 17422944501Smrg counts = res; 17522944501Smrg 17622944501Smrg if (res.count_fbs) { 17722944501Smrg res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t))); 17822944501Smrg if (!res.fb_id_ptr) 17922944501Smrg goto err_allocs; 18022944501Smrg } 18122944501Smrg if (res.count_crtcs) { 18222944501Smrg res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t))); 18322944501Smrg if (!res.crtc_id_ptr) 18422944501Smrg goto err_allocs; 18522944501Smrg } 18622944501Smrg if (res.count_connectors) { 18722944501Smrg res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t))); 18822944501Smrg if (!res.connector_id_ptr) 18922944501Smrg goto err_allocs; 19022944501Smrg } 19122944501Smrg if (res.count_encoders) { 19222944501Smrg res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t))); 19322944501Smrg if (!res.encoder_id_ptr) 19422944501Smrg goto err_allocs; 19522944501Smrg } 19622944501Smrg 19722944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 19822944501Smrg goto err_allocs; 19922944501Smrg 20022944501Smrg /* The number of available connectors and etc may have changed with a 20122944501Smrg * hotplug event in between the ioctls, in which case the field is 20222944501Smrg * silently ignored by the kernel. 20322944501Smrg */ 20422944501Smrg if (counts.count_fbs < res.count_fbs || 20522944501Smrg counts.count_crtcs < res.count_crtcs || 20622944501Smrg counts.count_connectors < res.count_connectors || 20722944501Smrg counts.count_encoders < res.count_encoders) 20822944501Smrg { 20922944501Smrg drmFree(U642VOID(res.fb_id_ptr)); 21022944501Smrg drmFree(U642VOID(res.crtc_id_ptr)); 21122944501Smrg drmFree(U642VOID(res.connector_id_ptr)); 21222944501Smrg drmFree(U642VOID(res.encoder_id_ptr)); 21322944501Smrg 21422944501Smrg goto retry; 21522944501Smrg } 21622944501Smrg 21722944501Smrg /* 21822944501Smrg * return 21922944501Smrg */ 22022944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 22122944501Smrg goto err_allocs; 22222944501Smrg 22322944501Smrg r->min_width = res.min_width; 22422944501Smrg r->max_width = res.max_width; 22522944501Smrg r->min_height = res.min_height; 22622944501Smrg r->max_height = res.max_height; 22722944501Smrg r->count_fbs = res.count_fbs; 22822944501Smrg r->count_crtcs = res.count_crtcs; 22922944501Smrg r->count_connectors = res.count_connectors; 23022944501Smrg r->count_encoders = res.count_encoders; 23122944501Smrg 23222944501Smrg r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t)); 23322944501Smrg r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t)); 23422944501Smrg r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t)); 23522944501Smrg r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t)); 23622944501Smrg if ((res.count_fbs && !r->fbs) || 23722944501Smrg (res.count_crtcs && !r->crtcs) || 23822944501Smrg (res.count_connectors && !r->connectors) || 23922944501Smrg (res.count_encoders && !r->encoders)) 24022944501Smrg { 24122944501Smrg drmFree(r->fbs); 24222944501Smrg drmFree(r->crtcs); 24322944501Smrg drmFree(r->connectors); 24422944501Smrg drmFree(r->encoders); 24522944501Smrg drmFree(r); 24622944501Smrg r = 0; 24722944501Smrg } 24822944501Smrg 24922944501Smrgerr_allocs: 25022944501Smrg drmFree(U642VOID(res.fb_id_ptr)); 25122944501Smrg drmFree(U642VOID(res.crtc_id_ptr)); 25222944501Smrg drmFree(U642VOID(res.connector_id_ptr)); 25322944501Smrg drmFree(U642VOID(res.encoder_id_ptr)); 25422944501Smrg 25522944501Smrg return r; 25622944501Smrg} 25722944501Smrg 2586260e5d5Smrg 2596260e5d5Smrgdrm_public int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, 2606260e5d5Smrg uint8_t bpp, uint32_t pitch, uint32_t bo_handle, 2616260e5d5Smrg uint32_t *buf_id) 26222944501Smrg{ 26322944501Smrg struct drm_mode_fb_cmd f; 26422944501Smrg int ret; 26522944501Smrg 266424e9256Smrg memclear(f); 26722944501Smrg f.width = width; 26822944501Smrg f.height = height; 26922944501Smrg f.pitch = pitch; 27022944501Smrg f.bpp = bpp; 27122944501Smrg f.depth = depth; 27222944501Smrg f.handle = bo_handle; 27322944501Smrg 274d049871aSmrg if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f))) 27522944501Smrg return ret; 27622944501Smrg 27722944501Smrg *buf_id = f.fb_id; 27822944501Smrg return 0; 27922944501Smrg} 28022944501Smrg 2816260e5d5Smrgdrm_public int drmModeAddFB2WithModifiers(int fd, uint32_t width, 2826260e5d5Smrg uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4], 2836260e5d5Smrg const uint32_t pitches[4], const uint32_t offsets[4], 2846260e5d5Smrg const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags) 285e88f27b3Smrg{ 286e88f27b3Smrg struct drm_mode_fb_cmd2 f; 287e88f27b3Smrg int ret; 288e88f27b3Smrg 289424e9256Smrg memclear(f); 290e88f27b3Smrg f.width = width; 291e88f27b3Smrg f.height = height; 292e88f27b3Smrg f.pixel_format = pixel_format; 293e88f27b3Smrg f.flags = flags; 294e88f27b3Smrg memcpy(f.handles, bo_handles, 4 * sizeof(bo_handles[0])); 295e88f27b3Smrg memcpy(f.pitches, pitches, 4 * sizeof(pitches[0])); 296e88f27b3Smrg memcpy(f.offsets, offsets, 4 * sizeof(offsets[0])); 297636d5e9fSmrg if (modifier) 2982ee35494Smrg memcpy(f.modifier, modifier, 4 * sizeof(modifier[0])); 299e88f27b3Smrg 300e88f27b3Smrg if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB2, &f))) 301e88f27b3Smrg return ret; 302e88f27b3Smrg 303e88f27b3Smrg *buf_id = f.fb_id; 304e88f27b3Smrg return 0; 305e88f27b3Smrg} 306e88f27b3Smrg 3076260e5d5Smrgdrm_public int drmModeAddFB2(int fd, uint32_t width, uint32_t height, 3086260e5d5Smrg uint32_t pixel_format, const uint32_t bo_handles[4], 3096260e5d5Smrg const uint32_t pitches[4], const uint32_t offsets[4], 3106260e5d5Smrg uint32_t *buf_id, uint32_t flags) 3112ee35494Smrg{ 3122ee35494Smrg return drmModeAddFB2WithModifiers(fd, width, height, 3132ee35494Smrg pixel_format, bo_handles, 3142ee35494Smrg pitches, offsets, NULL, 3152ee35494Smrg buf_id, flags); 3162ee35494Smrg} 3172ee35494Smrg 3186260e5d5Smrgdrm_public int drmModeRmFB(int fd, uint32_t bufferId) 31922944501Smrg{ 320d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); 32122944501Smrg} 32222944501Smrg 32348246ce7Smrgdrm_public int drmModeCloseFB(int fd, uint32_t buffer_id) 32448246ce7Smrg{ 32548246ce7Smrg struct drm_mode_closefb closefb; 32648246ce7Smrg 32748246ce7Smrg memclear(closefb); 32848246ce7Smrg closefb.fb_id = buffer_id; 32948246ce7Smrg 33048246ce7Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CLOSEFB, &closefb); 33148246ce7Smrg} 33248246ce7Smrg 3336260e5d5Smrgdrm_public drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) 33422944501Smrg{ 33522944501Smrg struct drm_mode_fb_cmd info; 33622944501Smrg drmModeFBPtr r; 33722944501Smrg 338424e9256Smrg memclear(info); 33922944501Smrg info.fb_id = buf; 34022944501Smrg 34122944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info)) 34222944501Smrg return NULL; 34322944501Smrg 34422944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 34522944501Smrg return NULL; 34622944501Smrg 34722944501Smrg r->fb_id = info.fb_id; 34822944501Smrg r->width = info.width; 34922944501Smrg r->height = info.height; 35022944501Smrg r->pitch = info.pitch; 35122944501Smrg r->bpp = info.bpp; 35222944501Smrg r->handle = info.handle; 35322944501Smrg r->depth = info.depth; 35422944501Smrg 35522944501Smrg return r; 35622944501Smrg} 35722944501Smrg 3586260e5d5Smrgdrm_public int drmModeDirtyFB(int fd, uint32_t bufferId, 35922944501Smrg drmModeClipPtr clips, uint32_t num_clips) 36022944501Smrg{ 361424e9256Smrg struct drm_mode_fb_dirty_cmd dirty; 36222944501Smrg 363424e9256Smrg memclear(dirty); 36422944501Smrg dirty.fb_id = bufferId; 36522944501Smrg dirty.clips_ptr = VOID2U64(clips); 36622944501Smrg dirty.num_clips = num_clips; 36722944501Smrg 368d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty); 36922944501Smrg} 37022944501Smrg 37122944501Smrg/* 37222944501Smrg * Crtc functions 37322944501Smrg */ 37422944501Smrg 3756260e5d5Smrgdrm_public drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) 37622944501Smrg{ 37722944501Smrg struct drm_mode_crtc crtc; 37822944501Smrg drmModeCrtcPtr r; 37922944501Smrg 380424e9256Smrg memclear(crtc); 38122944501Smrg crtc.crtc_id = crtcId; 38222944501Smrg 38322944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc)) 38422944501Smrg return 0; 38522944501Smrg 38622944501Smrg /* 38722944501Smrg * return 38822944501Smrg */ 38922944501Smrg 39022944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 39122944501Smrg return 0; 39222944501Smrg 39322944501Smrg r->crtc_id = crtc.crtc_id; 39422944501Smrg r->x = crtc.x; 39522944501Smrg r->y = crtc.y; 39622944501Smrg r->mode_valid = crtc.mode_valid; 397e88f27b3Smrg if (r->mode_valid) { 39822944501Smrg memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo)); 399e88f27b3Smrg r->width = crtc.mode.hdisplay; 400e88f27b3Smrg r->height = crtc.mode.vdisplay; 401e88f27b3Smrg } 40222944501Smrg r->buffer_id = crtc.fb_id; 40322944501Smrg r->gamma_size = crtc.gamma_size; 40422944501Smrg return r; 40522944501Smrg} 40622944501Smrg 4076260e5d5Smrgdrm_public int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, 408fe517fc9Smrg uint32_t x, uint32_t y, uint32_t *connectors, int count, 40922944501Smrg drmModeModeInfoPtr mode) 41022944501Smrg{ 41122944501Smrg struct drm_mode_crtc crtc; 41222944501Smrg 413424e9256Smrg memclear(crtc); 41422944501Smrg crtc.x = x; 41522944501Smrg crtc.y = y; 41622944501Smrg crtc.crtc_id = crtcId; 41722944501Smrg crtc.fb_id = bufferId; 41822944501Smrg crtc.set_connectors_ptr = VOID2U64(connectors); 41922944501Smrg crtc.count_connectors = count; 42022944501Smrg if (mode) { 42122944501Smrg memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo)); 42222944501Smrg crtc.mode_valid = 1; 423424e9256Smrg } 42422944501Smrg 425d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); 42622944501Smrg} 42722944501Smrg 42822944501Smrg/* 42922944501Smrg * Cursor manipulation 43022944501Smrg */ 43122944501Smrg 4326260e5d5Smrgdrm_public int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, 4336260e5d5Smrg uint32_t width, uint32_t height) 43422944501Smrg{ 43522944501Smrg struct drm_mode_cursor arg; 43622944501Smrg 437424e9256Smrg memclear(arg); 43822944501Smrg arg.flags = DRM_MODE_CURSOR_BO; 43922944501Smrg arg.crtc_id = crtcId; 44022944501Smrg arg.width = width; 44122944501Smrg arg.height = height; 44222944501Smrg arg.handle = bo_handle; 44322944501Smrg 444d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 44522944501Smrg} 44622944501Smrg 4476260e5d5Smrgdrm_public int drmModeSetCursor2(int fd, uint32_t crtcId, uint32_t bo_handle, 4486260e5d5Smrg uint32_t width, uint32_t height, int32_t hot_x, 4496260e5d5Smrg int32_t hot_y) 450e88f27b3Smrg{ 451e88f27b3Smrg struct drm_mode_cursor2 arg; 452e88f27b3Smrg 453424e9256Smrg memclear(arg); 454e88f27b3Smrg arg.flags = DRM_MODE_CURSOR_BO; 455e88f27b3Smrg arg.crtc_id = crtcId; 456e88f27b3Smrg arg.width = width; 457e88f27b3Smrg arg.height = height; 458e88f27b3Smrg arg.handle = bo_handle; 459e88f27b3Smrg arg.hot_x = hot_x; 460e88f27b3Smrg arg.hot_y = hot_y; 461e88f27b3Smrg 462e88f27b3Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR2, &arg); 463e88f27b3Smrg} 464e88f27b3Smrg 4656260e5d5Smrgdrm_public int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) 46622944501Smrg{ 46722944501Smrg struct drm_mode_cursor arg; 46822944501Smrg 469424e9256Smrg memclear(arg); 47022944501Smrg arg.flags = DRM_MODE_CURSOR_MOVE; 47122944501Smrg arg.crtc_id = crtcId; 47222944501Smrg arg.x = x; 47322944501Smrg arg.y = y; 47422944501Smrg 475d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 47622944501Smrg} 47722944501Smrg 47822944501Smrg/* 47922944501Smrg * Encoder get 48022944501Smrg */ 4816260e5d5Smrgdrm_public drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) 48222944501Smrg{ 48322944501Smrg struct drm_mode_get_encoder enc; 48422944501Smrg drmModeEncoderPtr r = NULL; 48522944501Smrg 486424e9256Smrg memclear(enc); 48722944501Smrg enc.encoder_id = encoder_id; 48822944501Smrg 48922944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc)) 49022944501Smrg return 0; 49122944501Smrg 49222944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 49322944501Smrg return 0; 49422944501Smrg 49522944501Smrg r->encoder_id = enc.encoder_id; 49622944501Smrg r->crtc_id = enc.crtc_id; 49722944501Smrg r->encoder_type = enc.encoder_type; 49822944501Smrg r->possible_crtcs = enc.possible_crtcs; 49922944501Smrg r->possible_clones = enc.possible_clones; 50022944501Smrg 50122944501Smrg return r; 50222944501Smrg} 50322944501Smrg 50422944501Smrg/* 50522944501Smrg * Connector manipulation 50622944501Smrg */ 507424e9256Smrgstatic drmModeConnectorPtr 508424e9256Smrg_drmModeGetConnector(int fd, uint32_t connector_id, int probe) 50922944501Smrg{ 51022944501Smrg struct drm_mode_get_connector conn, counts; 51122944501Smrg drmModeConnectorPtr r = NULL; 512fe517fc9Smrg struct drm_mode_modeinfo stack_mode; 51322944501Smrg 514424e9256Smrg memclear(conn); 51522944501Smrg conn.connector_id = connector_id; 516424e9256Smrg if (!probe) { 517424e9256Smrg conn.count_modes = 1; 518fe517fc9Smrg conn.modes_ptr = VOID2U64(&stack_mode); 519424e9256Smrg } 52022944501Smrg 52122944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 52222944501Smrg return 0; 52322944501Smrg 524424e9256Smrgretry: 52522944501Smrg counts = conn; 52622944501Smrg 52722944501Smrg if (conn.count_props) { 52822944501Smrg conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t))); 52922944501Smrg if (!conn.props_ptr) 53022944501Smrg goto err_allocs; 53122944501Smrg conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t))); 53222944501Smrg if (!conn.prop_values_ptr) 53322944501Smrg goto err_allocs; 53422944501Smrg } 53522944501Smrg 53622944501Smrg if (conn.count_modes) { 53722944501Smrg conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); 53822944501Smrg if (!conn.modes_ptr) 53922944501Smrg goto err_allocs; 540424e9256Smrg } else { 541424e9256Smrg conn.count_modes = 1; 542fe517fc9Smrg conn.modes_ptr = VOID2U64(&stack_mode); 54322944501Smrg } 54422944501Smrg 54522944501Smrg if (conn.count_encoders) { 54622944501Smrg conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t))); 54722944501Smrg if (!conn.encoders_ptr) 54822944501Smrg goto err_allocs; 54922944501Smrg } 55022944501Smrg 55122944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 55222944501Smrg goto err_allocs; 55322944501Smrg 55422944501Smrg /* The number of available connectors and etc may have changed with a 55522944501Smrg * hotplug event in between the ioctls, in which case the field is 55622944501Smrg * silently ignored by the kernel. 55722944501Smrg */ 55822944501Smrg if (counts.count_props < conn.count_props || 55922944501Smrg counts.count_modes < conn.count_modes || 56022944501Smrg counts.count_encoders < conn.count_encoders) { 56122944501Smrg drmFree(U642VOID(conn.props_ptr)); 56222944501Smrg drmFree(U642VOID(conn.prop_values_ptr)); 563fe517fc9Smrg if (U642VOID(conn.modes_ptr) != &stack_mode) 564fe517fc9Smrg drmFree(U642VOID(conn.modes_ptr)); 56522944501Smrg drmFree(U642VOID(conn.encoders_ptr)); 56622944501Smrg 56722944501Smrg goto retry; 56822944501Smrg } 56922944501Smrg 57022944501Smrg if(!(r = drmMalloc(sizeof(*r)))) { 57122944501Smrg goto err_allocs; 57222944501Smrg } 57322944501Smrg 57422944501Smrg r->connector_id = conn.connector_id; 57522944501Smrg r->encoder_id = conn.encoder_id; 57622944501Smrg r->connection = conn.connection; 57722944501Smrg r->mmWidth = conn.mm_width; 57822944501Smrg r->mmHeight = conn.mm_height; 57922944501Smrg /* convert subpixel from kernel to userspace */ 58022944501Smrg r->subpixel = conn.subpixel + 1; 58122944501Smrg r->count_modes = conn.count_modes; 58222944501Smrg r->count_props = conn.count_props; 58322944501Smrg r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t)); 58422944501Smrg r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t)); 58522944501Smrg r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo)); 58622944501Smrg r->count_encoders = conn.count_encoders; 58722944501Smrg r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t)); 58822944501Smrg r->connector_type = conn.connector_type; 58922944501Smrg r->connector_type_id = conn.connector_type_id; 59022944501Smrg 59122944501Smrg if ((r->count_props && !r->props) || 59222944501Smrg (r->count_props && !r->prop_values) || 59322944501Smrg (r->count_modes && !r->modes) || 59422944501Smrg (r->count_encoders && !r->encoders)) { 59522944501Smrg drmFree(r->props); 59622944501Smrg drmFree(r->prop_values); 59722944501Smrg drmFree(r->modes); 59822944501Smrg drmFree(r->encoders); 59922944501Smrg drmFree(r); 60022944501Smrg r = 0; 60122944501Smrg } 60222944501Smrg 60322944501Smrgerr_allocs: 60422944501Smrg drmFree(U642VOID(conn.prop_values_ptr)); 60522944501Smrg drmFree(U642VOID(conn.props_ptr)); 606fe517fc9Smrg if (U642VOID(conn.modes_ptr) != &stack_mode) 607fe517fc9Smrg drmFree(U642VOID(conn.modes_ptr)); 60822944501Smrg drmFree(U642VOID(conn.encoders_ptr)); 60922944501Smrg 61022944501Smrg return r; 61122944501Smrg} 61222944501Smrg 6136260e5d5Smrgdrm_public drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) 614424e9256Smrg{ 615424e9256Smrg return _drmModeGetConnector(fd, connector_id, 1); 616424e9256Smrg} 617424e9256Smrg 6186260e5d5Smrgdrm_public drmModeConnectorPtr drmModeGetConnectorCurrent(int fd, uint32_t connector_id) 619424e9256Smrg{ 620424e9256Smrg return _drmModeGetConnector(fd, connector_id, 0); 621424e9256Smrg} 622424e9256Smrg 62350027b5bSmrgdrm_public uint32_t drmModeConnectorGetPossibleCrtcs(int fd, 62450027b5bSmrg const drmModeConnector *connector) 62550027b5bSmrg{ 62650027b5bSmrg drmModeEncoder *encoder; 62750027b5bSmrg int i; 62850027b5bSmrg uint32_t possible_crtcs; 62950027b5bSmrg 63050027b5bSmrg possible_crtcs = 0; 63150027b5bSmrg for (i = 0; i < connector->count_encoders; i++) { 63250027b5bSmrg encoder = drmModeGetEncoder(fd, connector->encoders[i]); 63350027b5bSmrg if (!encoder) { 63450027b5bSmrg return 0; 63550027b5bSmrg } 63650027b5bSmrg 63750027b5bSmrg possible_crtcs |= encoder->possible_crtcs; 63850027b5bSmrg drmModeFreeEncoder(encoder); 63950027b5bSmrg } 64050027b5bSmrg 64150027b5bSmrg if (possible_crtcs == 0) 64250027b5bSmrg errno = ENOENT; 64350027b5bSmrg return possible_crtcs; 64450027b5bSmrg} 64550027b5bSmrg 6466260e5d5Smrgdrm_public int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 64722944501Smrg{ 64822944501Smrg struct drm_mode_mode_cmd res; 64922944501Smrg 650424e9256Smrg memclear(res); 65122944501Smrg memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 65222944501Smrg res.connector_id = connector_id; 65322944501Smrg 654d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); 65522944501Smrg} 65622944501Smrg 6576260e5d5Smrgdrm_public int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 65822944501Smrg{ 65922944501Smrg struct drm_mode_mode_cmd res; 66022944501Smrg 661424e9256Smrg memclear(res); 66222944501Smrg memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 66322944501Smrg res.connector_id = connector_id; 66422944501Smrg 665d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res); 66622944501Smrg} 66722944501Smrg 6686260e5d5Smrgdrm_public drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) 66922944501Smrg{ 67022944501Smrg struct drm_mode_get_property prop; 67122944501Smrg drmModePropertyPtr r; 67222944501Smrg 673424e9256Smrg memclear(prop); 67422944501Smrg prop.prop_id = property_id; 67522944501Smrg 67622944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) 67722944501Smrg return 0; 67822944501Smrg 67922944501Smrg if (prop.count_values) 68022944501Smrg prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t))); 68122944501Smrg 682e88f27b3Smrg if (prop.count_enum_blobs && (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) 68322944501Smrg prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum))); 68422944501Smrg 68522944501Smrg if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) { 68622944501Smrg prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 68722944501Smrg prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 68822944501Smrg } 68922944501Smrg 69022944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) { 69122944501Smrg r = NULL; 69222944501Smrg goto err_allocs; 69322944501Smrg } 69422944501Smrg 69522944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 696bf6cc7dcSmrg goto err_allocs; 69722944501Smrg 69822944501Smrg r->prop_id = prop.prop_id; 69922944501Smrg r->count_values = prop.count_values; 70022944501Smrg 70122944501Smrg r->flags = prop.flags; 70222944501Smrg if (prop.count_values) 70322944501Smrg r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t)); 704e88f27b3Smrg if (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { 70522944501Smrg r->count_enums = prop.count_enum_blobs; 70622944501Smrg r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); 70722944501Smrg } else if (prop.flags & DRM_MODE_PROP_BLOB) { 70822944501Smrg r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 70922944501Smrg r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 71022944501Smrg r->count_blobs = prop.count_enum_blobs; 71122944501Smrg } 71222944501Smrg strncpy(r->name, prop.name, DRM_PROP_NAME_LEN); 71322944501Smrg r->name[DRM_PROP_NAME_LEN-1] = 0; 71422944501Smrg 71522944501Smrgerr_allocs: 71622944501Smrg drmFree(U642VOID(prop.values_ptr)); 71722944501Smrg drmFree(U642VOID(prop.enum_blob_ptr)); 71822944501Smrg 71922944501Smrg return r; 72022944501Smrg} 72122944501Smrg 7226260e5d5Smrgdrm_public void drmModeFreeProperty(drmModePropertyPtr ptr) 72322944501Smrg{ 72422944501Smrg if (!ptr) 72522944501Smrg return; 72622944501Smrg 72722944501Smrg drmFree(ptr->values); 72822944501Smrg drmFree(ptr->enums); 72987bf8e7cSmrg drmFree(ptr->blob_ids); 73022944501Smrg drmFree(ptr); 73122944501Smrg} 73222944501Smrg 7336260e5d5Smrgdrm_public drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, 7346260e5d5Smrg uint32_t blob_id) 73522944501Smrg{ 73622944501Smrg struct drm_mode_get_blob blob; 73722944501Smrg drmModePropertyBlobPtr r; 73822944501Smrg 739424e9256Smrg memclear(blob); 74022944501Smrg blob.blob_id = blob_id; 74122944501Smrg 74222944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) 74322944501Smrg return NULL; 74422944501Smrg 74522944501Smrg if (blob.length) 74622944501Smrg blob.data = VOID2U64(drmMalloc(blob.length)); 74722944501Smrg 74822944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) { 74922944501Smrg r = NULL; 75022944501Smrg goto err_allocs; 75122944501Smrg } 75222944501Smrg 75322944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 754d049871aSmrg goto err_allocs; 75522944501Smrg 75622944501Smrg r->id = blob.blob_id; 75722944501Smrg r->length = blob.length; 75822944501Smrg r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length); 75922944501Smrg 76022944501Smrgerr_allocs: 76122944501Smrg drmFree(U642VOID(blob.data)); 76222944501Smrg return r; 76322944501Smrg} 76422944501Smrg 765adfa0b0cSmrgstatic inline const uint32_t * 766adfa0b0cSmrgget_formats_ptr(const struct drm_format_modifier_blob *blob) 767adfa0b0cSmrg{ 768adfa0b0cSmrg return (const uint32_t *)(((uint8_t *)blob) + blob->formats_offset); 769adfa0b0cSmrg} 770adfa0b0cSmrg 771adfa0b0cSmrgstatic inline const struct drm_format_modifier * 772adfa0b0cSmrgget_modifiers_ptr(const struct drm_format_modifier_blob *blob) 773adfa0b0cSmrg{ 774adfa0b0cSmrg return (const struct drm_format_modifier *)(((uint8_t *)blob) + 775adfa0b0cSmrg blob->modifiers_offset); 776adfa0b0cSmrg} 777adfa0b0cSmrg 778adfa0b0cSmrgstatic bool _drmModeFormatModifierGetNext(const drmModePropertyBlobRes *blob, 779adfa0b0cSmrg drmModeFormatModifierIterator *iter) 780adfa0b0cSmrg{ 781adfa0b0cSmrg const struct drm_format_modifier *blob_modifiers, *mod; 782adfa0b0cSmrg const struct drm_format_modifier_blob *fmt_mod_blob; 783adfa0b0cSmrg const uint32_t *blob_formats; 784adfa0b0cSmrg 785adfa0b0cSmrg assert(blob && iter); 786adfa0b0cSmrg 787adfa0b0cSmrg fmt_mod_blob = blob->data; 788adfa0b0cSmrg blob_modifiers = get_modifiers_ptr(fmt_mod_blob); 789adfa0b0cSmrg blob_formats = get_formats_ptr(fmt_mod_blob); 790adfa0b0cSmrg 791adfa0b0cSmrg /* fmt_idx and mod_idx designate the number of processed formats 792adfa0b0cSmrg * and modifiers. 793adfa0b0cSmrg */ 794adfa0b0cSmrg if (iter->fmt_idx >= fmt_mod_blob->count_formats || 795adfa0b0cSmrg iter->mod_idx >= fmt_mod_blob->count_modifiers) 796adfa0b0cSmrg return false; 797adfa0b0cSmrg 798adfa0b0cSmrg iter->fmt = blob_formats[iter->fmt_idx]; 799adfa0b0cSmrg iter->mod = DRM_FORMAT_MOD_INVALID; 800adfa0b0cSmrg 801adfa0b0cSmrg /* From the latest valid found, get the next valid modifier */ 802adfa0b0cSmrg while (iter->mod_idx < fmt_mod_blob->count_modifiers) { 803adfa0b0cSmrg mod = &blob_modifiers[iter->mod_idx++]; 804adfa0b0cSmrg 805adfa0b0cSmrg /* Check if the format that fmt_idx designates, belongs to 806adfa0b0cSmrg * this modifier 64-bit window selected via mod->offset. 807adfa0b0cSmrg */ 808adfa0b0cSmrg if (iter->fmt_idx < mod->offset || 809adfa0b0cSmrg iter->fmt_idx >= mod->offset + 64) 810adfa0b0cSmrg continue; 811adfa0b0cSmrg if (!(mod->formats & (1 << (iter->fmt_idx - mod->offset)))) 812adfa0b0cSmrg continue; 813adfa0b0cSmrg 814adfa0b0cSmrg iter->mod = mod->modifier; 815adfa0b0cSmrg break; 816adfa0b0cSmrg } 817adfa0b0cSmrg 818adfa0b0cSmrg if (iter->mod_idx == fmt_mod_blob->count_modifiers) { 819adfa0b0cSmrg iter->mod_idx = 0; 820adfa0b0cSmrg iter->fmt_idx++; 821adfa0b0cSmrg } 822adfa0b0cSmrg 823adfa0b0cSmrg /* Since mod_idx reset, in order for the caller to iterate over 824adfa0b0cSmrg * the last modifier of the last format, always return true here 825adfa0b0cSmrg * and early return from the next call. 826adfa0b0cSmrg */ 827adfa0b0cSmrg return true; 828adfa0b0cSmrg} 829adfa0b0cSmrg 830adfa0b0cSmrg/** 831adfa0b0cSmrg * Iterate over formats first and then over modifiers. On each call, iter->fmt 832adfa0b0cSmrg * is retained until all associated modifiers are returned. Then, either update 833adfa0b0cSmrg * iter->fmt with the next format, or exit if there aren't any left. 834adfa0b0cSmrg * 835adfa0b0cSmrg * NOTE: clients should not make any assumption on mod_idx and fmt_idx values 836adfa0b0cSmrg * 837adfa0b0cSmrg * @blob: valid kernel blob holding formats and modifiers 838adfa0b0cSmrg * @iter: input and output iterator data. Iter data must be initialised to zero 839adfa0b0cSmrg * @return: false, on error or there aren't any further formats or modifiers left. 840adfa0b0cSmrg * true, on success and there are more formats or modifiers. 841adfa0b0cSmrg */ 842adfa0b0cSmrgdrm_public bool drmModeFormatModifierBlobIterNext(const drmModePropertyBlobRes *blob, 843adfa0b0cSmrg drmModeFormatModifierIterator *iter) 844adfa0b0cSmrg{ 845adfa0b0cSmrg drmModeFormatModifierIterator tmp; 846adfa0b0cSmrg bool has_fmt; 847adfa0b0cSmrg 848adfa0b0cSmrg if (!blob || !iter) 849adfa0b0cSmrg return false; 850adfa0b0cSmrg 851adfa0b0cSmrg tmp.fmt_idx = iter->fmt_idx; 852adfa0b0cSmrg tmp.mod_idx = iter->mod_idx; 853adfa0b0cSmrg 854adfa0b0cSmrg /* With the current state of things, DRM/KMS drivers are allowed to 855adfa0b0cSmrg * construct blobs having formats and no modifiers. Userspace can't 856adfa0b0cSmrg * legitimately abort in such cases. 857adfa0b0cSmrg * 858adfa0b0cSmrg * While waiting for the kernel to perhaps disallow formats with no 859adfa0b0cSmrg * modifiers in IN_FORMATS blobs, skip the format altogether. 860adfa0b0cSmrg */ 861adfa0b0cSmrg do { 862adfa0b0cSmrg has_fmt = _drmModeFormatModifierGetNext(blob, &tmp); 863adfa0b0cSmrg if (has_fmt && tmp.mod != DRM_FORMAT_MOD_INVALID) 864adfa0b0cSmrg *iter = tmp; 865adfa0b0cSmrg 866adfa0b0cSmrg } while (has_fmt && tmp.mod == DRM_FORMAT_MOD_INVALID); 867adfa0b0cSmrg 868adfa0b0cSmrg return has_fmt; 869adfa0b0cSmrg} 870adfa0b0cSmrg 8716260e5d5Smrgdrm_public void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) 87222944501Smrg{ 87322944501Smrg if (!ptr) 87422944501Smrg return; 87522944501Smrg 87622944501Smrg drmFree(ptr->data); 87722944501Smrg drmFree(ptr); 87822944501Smrg} 87922944501Smrg 8806260e5d5Smrgdrm_public int drmModeConnectorSetProperty(int fd, uint32_t connector_id, 8816260e5d5Smrg uint32_t property_id, 8826260e5d5Smrg uint64_t value) 88322944501Smrg{ 88422944501Smrg struct drm_mode_connector_set_property osp; 88522944501Smrg 886424e9256Smrg memclear(osp); 88722944501Smrg osp.connector_id = connector_id; 88822944501Smrg osp.prop_id = property_id; 88922944501Smrg osp.value = value; 89022944501Smrg 891d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp); 89222944501Smrg} 89322944501Smrg 89422944501Smrg/* 89522944501Smrg * checks if a modesetting capable driver has attached to the pci id 89622944501Smrg * returns 0 if modesetting supported. 89722944501Smrg * -EINVAL or invalid bus id 89822944501Smrg * -ENOSYS if no modesetting support 89922944501Smrg*/ 9006260e5d5Smrgdrm_public int drmCheckModesettingSupported(const char *busid) 90122944501Smrg{ 902a7d7de1eSmrg#if defined (__linux__) 90322944501Smrg char pci_dev_dir[1024]; 90422944501Smrg int domain, bus, dev, func; 90522944501Smrg DIR *sysdir; 90622944501Smrg struct dirent *dent; 90722944501Smrg int found = 0, ret; 90822944501Smrg 90922944501Smrg ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); 91022944501Smrg if (ret != 4) 91122944501Smrg return -EINVAL; 91222944501Smrg 91322944501Smrg sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm", 91422944501Smrg domain, bus, dev, func); 91522944501Smrg 91622944501Smrg sysdir = opendir(pci_dev_dir); 91722944501Smrg if (sysdir) { 91822944501Smrg dent = readdir(sysdir); 91922944501Smrg while (dent) { 92022944501Smrg if (!strncmp(dent->d_name, "controlD", 8)) { 92122944501Smrg found = 1; 92222944501Smrg break; 92322944501Smrg } 92422944501Smrg 92522944501Smrg dent = readdir(sysdir); 92622944501Smrg } 92722944501Smrg closedir(sysdir); 92822944501Smrg if (found) 92922944501Smrg return 0; 93022944501Smrg } 93122944501Smrg 93222944501Smrg sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/", 93322944501Smrg domain, bus, dev, func); 93422944501Smrg 93522944501Smrg sysdir = opendir(pci_dev_dir); 93622944501Smrg if (!sysdir) 93722944501Smrg return -EINVAL; 93822944501Smrg 93922944501Smrg dent = readdir(sysdir); 94022944501Smrg while (dent) { 94122944501Smrg if (!strncmp(dent->d_name, "drm:controlD", 12)) { 94222944501Smrg found = 1; 94322944501Smrg break; 94422944501Smrg } 94522944501Smrg 94622944501Smrg dent = readdir(sysdir); 94722944501Smrg } 94822944501Smrg 94922944501Smrg closedir(sysdir); 95022944501Smrg if (found) 95122944501Smrg return 0; 952a7d7de1eSmrg#elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) 95387bf8e7cSmrg char sbusid[1024]; 954a7d7de1eSmrg char oid[128]; 955a7d7de1eSmrg int i, modesetting, ret; 956a7d7de1eSmrg size_t len; 957a7d7de1eSmrg 958a7d7de1eSmrg /* How many GPUs do we expect in the machine ? */ 95987bf8e7cSmrg for (i = 0; i < 10; i++) { 960a7d7de1eSmrg snprintf(oid, sizeof(oid), "hw.dri.%d.busid", i); 961a7d7de1eSmrg len = sizeof(sbusid); 962a7d7de1eSmrg ret = sysctlbyname(oid, sbusid, &len, NULL, 0); 963a7d7de1eSmrg if (ret == -1) { 964a7d7de1eSmrg if (errno == ENOENT) 965a7d7de1eSmrg continue; 966a7d7de1eSmrg return -EINVAL; 967a7d7de1eSmrg } 96887bf8e7cSmrg if (strcmp(sbusid, busid) != 0) 969a7d7de1eSmrg continue; 970a7d7de1eSmrg snprintf(oid, sizeof(oid), "hw.dri.%d.modesetting", i); 971a7d7de1eSmrg len = sizeof(modesetting); 972a7d7de1eSmrg ret = sysctlbyname(oid, &modesetting, &len, NULL, 0); 973a7d7de1eSmrg if (ret == -1 || len != sizeof(modesetting)) 974a7d7de1eSmrg return -EINVAL; 975a7d7de1eSmrg return (modesetting ? 0 : -ENOSYS); 976a7d7de1eSmrg } 977e05f3551Smrg#elif defined(__DragonFly__) 978e05f3551Smrg return 0; 9796260e5d5Smrg#elif defined(__OpenBSD__) || defined(__NetBSD__) 980fe517fc9Smrg int fd; 981fe517fc9Smrg struct drm_mode_card_res res; 982fe517fc9Smrg drmModeResPtr r = 0; 983fe517fc9Smrg 984fe517fc9Smrg if ((fd = drmOpen(NULL, busid)) < 0) 985fe517fc9Smrg return -EINVAL; 9867d13a5d0Sriastradh 987fe517fc9Smrg memset(&res, 0, sizeof(struct drm_mode_card_res)); 988fe517fc9Smrg 989fe517fc9Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) { 990fe517fc9Smrg drmClose(fd); 991fe517fc9Smrg return -errno; 992fe517fc9Smrg } 993fe517fc9Smrg 994fe517fc9Smrg drmClose(fd); 995fe517fc9Smrg return 0; 996fe517fc9Smrg#endif 997fe517fc9Smrg return -ENOSYS; 99822944501Smrg} 99922944501Smrg 10006260e5d5Smrgdrm_public int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, 10016260e5d5Smrg uint16_t *red, uint16_t *green, 10026260e5d5Smrg uint16_t *blue) 100322944501Smrg{ 100422944501Smrg struct drm_mode_crtc_lut l; 100522944501Smrg 1006424e9256Smrg memclear(l); 100722944501Smrg l.crtc_id = crtc_id; 100822944501Smrg l.gamma_size = size; 100922944501Smrg l.red = VOID2U64(red); 101022944501Smrg l.green = VOID2U64(green); 101122944501Smrg l.blue = VOID2U64(blue); 101222944501Smrg 1013d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l); 101422944501Smrg} 101522944501Smrg 10166260e5d5Smrgdrm_public int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, 101748246ce7Smrg const uint16_t *red, const uint16_t *green, 101848246ce7Smrg const uint16_t *blue) 101922944501Smrg{ 102022944501Smrg struct drm_mode_crtc_lut l; 102122944501Smrg 1022424e9256Smrg memclear(l); 102322944501Smrg l.crtc_id = crtc_id; 102422944501Smrg l.gamma_size = size; 102522944501Smrg l.red = VOID2U64(red); 102622944501Smrg l.green = VOID2U64(green); 102722944501Smrg l.blue = VOID2U64(blue); 102822944501Smrg 1029d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l); 103022944501Smrg} 103122944501Smrg 10326260e5d5Smrgdrm_public int drmHandleEvent(int fd, drmEventContextPtr evctx) 103322944501Smrg{ 103422944501Smrg char buffer[1024]; 103522944501Smrg int len, i; 103622944501Smrg struct drm_event *e; 103722944501Smrg struct drm_event_vblank *vblank; 10382b90624aSmrg struct drm_event_crtc_sequence *seq; 10390655efefSmrg void *user_data; 1040fe517fc9Smrg 104122944501Smrg /* The DRM read semantics guarantees that we always get only 104222944501Smrg * complete events. */ 104322944501Smrg 104422944501Smrg len = read(fd, buffer, sizeof buffer); 104522944501Smrg if (len == 0) 104622944501Smrg return 0; 1047424e9256Smrg if (len < (int)sizeof *e) 104822944501Smrg return -1; 104922944501Smrg 105022944501Smrg i = 0; 105122944501Smrg while (i < len) { 10522ee35494Smrg e = (struct drm_event *)(buffer + i); 105322944501Smrg switch (e->type) { 105422944501Smrg case DRM_EVENT_VBLANK: 105522944501Smrg if (evctx->version < 1 || 105622944501Smrg evctx->vblank_handler == NULL) 105722944501Smrg break; 105822944501Smrg vblank = (struct drm_event_vblank *) e; 105922944501Smrg evctx->vblank_handler(fd, 1060fe517fc9Smrg vblank->sequence, 106122944501Smrg vblank->tv_sec, 106222944501Smrg vblank->tv_usec, 106322944501Smrg U642VOID (vblank->user_data)); 106422944501Smrg break; 106522944501Smrg case DRM_EVENT_FLIP_COMPLETE: 106622944501Smrg vblank = (struct drm_event_vblank *) e; 10670655efefSmrg user_data = U642VOID (vblank->user_data); 10680655efefSmrg 10690655efefSmrg if (evctx->version >= 3 && evctx->page_flip_handler2) 10700655efefSmrg evctx->page_flip_handler2(fd, 10710655efefSmrg vblank->sequence, 10720655efefSmrg vblank->tv_sec, 10730655efefSmrg vblank->tv_usec, 10740655efefSmrg vblank->crtc_id, 10750655efefSmrg user_data); 10760655efefSmrg else if (evctx->version >= 2 && evctx->page_flip_handler) 10770655efefSmrg evctx->page_flip_handler(fd, 10780655efefSmrg vblank->sequence, 10790655efefSmrg vblank->tv_sec, 10800655efefSmrg vblank->tv_usec, 10810655efefSmrg user_data); 108222944501Smrg break; 10832b90624aSmrg case DRM_EVENT_CRTC_SEQUENCE: 10842b90624aSmrg seq = (struct drm_event_crtc_sequence *) e; 10852b90624aSmrg if (evctx->version >= 4 && evctx->sequence_handler) 10862b90624aSmrg evctx->sequence_handler(fd, 10872b90624aSmrg seq->sequence, 10882b90624aSmrg seq->time_ns, 10892b90624aSmrg seq->user_data); 10902b90624aSmrg break; 109122944501Smrg default: 109222944501Smrg break; 109322944501Smrg } 109422944501Smrg i += e->length; 109522944501Smrg } 109622944501Smrg 109722944501Smrg return 0; 109822944501Smrg} 109922944501Smrg 11006260e5d5Smrgdrm_public int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, 110122944501Smrg uint32_t flags, void *user_data) 110222944501Smrg{ 110322944501Smrg struct drm_mode_crtc_page_flip flip; 110422944501Smrg 1105424e9256Smrg memclear(flip); 110622944501Smrg flip.fb_id = fb_id; 110722944501Smrg flip.crtc_id = crtc_id; 110822944501Smrg flip.user_data = VOID2U64(user_data); 110922944501Smrg flip.flags = flags; 111022944501Smrg 1111d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); 111222944501Smrg} 1113e88f27b3Smrg 11146260e5d5Smrgdrm_public int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id, 11152ee35494Smrg uint32_t flags, void *user_data, 11162ee35494Smrg uint32_t target_vblank) 11172ee35494Smrg{ 11182ee35494Smrg struct drm_mode_crtc_page_flip_target flip_target; 11192ee35494Smrg 11202ee35494Smrg memclear(flip_target); 11212ee35494Smrg flip_target.fb_id = fb_id; 11222ee35494Smrg flip_target.crtc_id = crtc_id; 11232ee35494Smrg flip_target.user_data = VOID2U64(user_data); 11242ee35494Smrg flip_target.flags = flags; 11252ee35494Smrg flip_target.sequence = target_vblank; 11262ee35494Smrg 11272ee35494Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip_target); 11282ee35494Smrg} 11292ee35494Smrg 11306260e5d5Smrgdrm_public int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id, 1131e88f27b3Smrg uint32_t fb_id, uint32_t flags, 1132becaf760Smrg uint32_t crtc_x, uint32_t crtc_y, 1133e88f27b3Smrg uint32_t crtc_w, uint32_t crtc_h, 1134e88f27b3Smrg uint32_t src_x, uint32_t src_y, 1135e88f27b3Smrg uint32_t src_w, uint32_t src_h) 1136e88f27b3Smrg{ 1137e88f27b3Smrg struct drm_mode_set_plane s; 1138e88f27b3Smrg 1139424e9256Smrg memclear(s); 1140e88f27b3Smrg s.plane_id = plane_id; 1141e88f27b3Smrg s.crtc_id = crtc_id; 1142e88f27b3Smrg s.fb_id = fb_id; 1143e88f27b3Smrg s.flags = flags; 1144e88f27b3Smrg s.crtc_x = crtc_x; 1145e88f27b3Smrg s.crtc_y = crtc_y; 1146e88f27b3Smrg s.crtc_w = crtc_w; 1147e88f27b3Smrg s.crtc_h = crtc_h; 1148e88f27b3Smrg s.src_x = src_x; 1149e88f27b3Smrg s.src_y = src_y; 1150e88f27b3Smrg s.src_w = src_w; 1151e88f27b3Smrg s.src_h = src_h; 1152e88f27b3Smrg 1153e88f27b3Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s); 1154e88f27b3Smrg} 1155e88f27b3Smrg 11566260e5d5Smrgdrm_public drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id) 1157e88f27b3Smrg{ 1158e88f27b3Smrg struct drm_mode_get_plane ovr, counts; 1159e88f27b3Smrg drmModePlanePtr r = 0; 1160e88f27b3Smrg 1161e88f27b3Smrgretry: 1162424e9256Smrg memclear(ovr); 1163e88f27b3Smrg ovr.plane_id = plane_id; 1164e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) 1165e88f27b3Smrg return 0; 1166e88f27b3Smrg 1167e88f27b3Smrg counts = ovr; 1168e88f27b3Smrg 1169e88f27b3Smrg if (ovr.count_format_types) { 1170e88f27b3Smrg ovr.format_type_ptr = VOID2U64(drmMalloc(ovr.count_format_types * 1171e88f27b3Smrg sizeof(uint32_t))); 1172e88f27b3Smrg if (!ovr.format_type_ptr) 1173e88f27b3Smrg goto err_allocs; 1174e88f27b3Smrg } 1175e88f27b3Smrg 1176e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr)) 1177e88f27b3Smrg goto err_allocs; 1178e88f27b3Smrg 1179e88f27b3Smrg if (counts.count_format_types < ovr.count_format_types) { 1180e88f27b3Smrg drmFree(U642VOID(ovr.format_type_ptr)); 1181e88f27b3Smrg goto retry; 1182e88f27b3Smrg } 1183e88f27b3Smrg 1184e88f27b3Smrg if (!(r = drmMalloc(sizeof(*r)))) 1185e88f27b3Smrg goto err_allocs; 1186e88f27b3Smrg 1187e88f27b3Smrg r->count_formats = ovr.count_format_types; 1188e88f27b3Smrg r->plane_id = ovr.plane_id; 1189e88f27b3Smrg r->crtc_id = ovr.crtc_id; 1190e88f27b3Smrg r->fb_id = ovr.fb_id; 1191e88f27b3Smrg r->possible_crtcs = ovr.possible_crtcs; 1192e88f27b3Smrg r->gamma_size = ovr.gamma_size; 1193e88f27b3Smrg r->formats = drmAllocCpy(U642VOID(ovr.format_type_ptr), 1194e88f27b3Smrg ovr.count_format_types, sizeof(uint32_t)); 1195e88f27b3Smrg if (ovr.count_format_types && !r->formats) { 1196e88f27b3Smrg drmFree(r->formats); 1197e88f27b3Smrg drmFree(r); 1198e88f27b3Smrg r = 0; 1199e88f27b3Smrg } 1200e88f27b3Smrg 1201e88f27b3Smrgerr_allocs: 1202e88f27b3Smrg drmFree(U642VOID(ovr.format_type_ptr)); 1203e88f27b3Smrg 1204e88f27b3Smrg return r; 1205e88f27b3Smrg} 1206e88f27b3Smrg 12076260e5d5Smrgdrm_public void drmModeFreePlane(drmModePlanePtr ptr) 1208e88f27b3Smrg{ 1209e88f27b3Smrg if (!ptr) 1210e88f27b3Smrg return; 1211e88f27b3Smrg 1212e88f27b3Smrg drmFree(ptr->formats); 1213e88f27b3Smrg drmFree(ptr); 1214e88f27b3Smrg} 1215e88f27b3Smrg 12166260e5d5Smrgdrm_public drmModePlaneResPtr drmModeGetPlaneResources(int fd) 1217e88f27b3Smrg{ 1218e88f27b3Smrg struct drm_mode_get_plane_res res, counts; 1219e88f27b3Smrg drmModePlaneResPtr r = 0; 1220e88f27b3Smrg 1221e88f27b3Smrgretry: 1222424e9256Smrg memclear(res); 1223e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) 1224e88f27b3Smrg return 0; 1225e88f27b3Smrg 1226e88f27b3Smrg counts = res; 1227e88f27b3Smrg 1228e88f27b3Smrg if (res.count_planes) { 1229e88f27b3Smrg res.plane_id_ptr = VOID2U64(drmMalloc(res.count_planes * 1230e88f27b3Smrg sizeof(uint32_t))); 1231e88f27b3Smrg if (!res.plane_id_ptr) 1232e88f27b3Smrg goto err_allocs; 1233e88f27b3Smrg } 1234e88f27b3Smrg 1235e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res)) 1236e88f27b3Smrg goto err_allocs; 1237e88f27b3Smrg 1238e88f27b3Smrg if (counts.count_planes < res.count_planes) { 1239e88f27b3Smrg drmFree(U642VOID(res.plane_id_ptr)); 1240e88f27b3Smrg goto retry; 1241e88f27b3Smrg } 1242e88f27b3Smrg 1243e88f27b3Smrg if (!(r = drmMalloc(sizeof(*r)))) 1244e88f27b3Smrg goto err_allocs; 1245e88f27b3Smrg 1246e88f27b3Smrg r->count_planes = res.count_planes; 1247e88f27b3Smrg r->planes = drmAllocCpy(U642VOID(res.plane_id_ptr), 1248e88f27b3Smrg res.count_planes, sizeof(uint32_t)); 1249e88f27b3Smrg if (res.count_planes && !r->planes) { 1250e88f27b3Smrg drmFree(r->planes); 1251e88f27b3Smrg drmFree(r); 1252e88f27b3Smrg r = 0; 1253e88f27b3Smrg } 1254e88f27b3Smrg 1255e88f27b3Smrgerr_allocs: 1256e88f27b3Smrg drmFree(U642VOID(res.plane_id_ptr)); 1257e88f27b3Smrg 1258e88f27b3Smrg return r; 1259e88f27b3Smrg} 1260e88f27b3Smrg 12616260e5d5Smrgdrm_public void drmModeFreePlaneResources(drmModePlaneResPtr ptr) 1262e88f27b3Smrg{ 1263e88f27b3Smrg if (!ptr) 1264e88f27b3Smrg return; 1265e88f27b3Smrg 1266e88f27b3Smrg drmFree(ptr->planes); 1267e88f27b3Smrg drmFree(ptr); 1268e88f27b3Smrg} 1269e88f27b3Smrg 12706260e5d5Smrgdrm_public drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd, 1271e88f27b3Smrg uint32_t object_id, 1272e88f27b3Smrg uint32_t object_type) 1273e88f27b3Smrg{ 1274e88f27b3Smrg struct drm_mode_obj_get_properties properties; 1275e88f27b3Smrg drmModeObjectPropertiesPtr ret = NULL; 1276e88f27b3Smrg uint32_t count; 1277e88f27b3Smrg 1278e88f27b3Smrgretry: 1279424e9256Smrg memclear(properties); 1280e88f27b3Smrg properties.obj_id = object_id; 1281e88f27b3Smrg properties.obj_type = object_type; 1282e88f27b3Smrg 1283e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) 1284e88f27b3Smrg return 0; 1285e88f27b3Smrg 1286e88f27b3Smrg count = properties.count_props; 1287e88f27b3Smrg 1288e88f27b3Smrg if (count) { 1289e88f27b3Smrg properties.props_ptr = VOID2U64(drmMalloc(count * 1290e88f27b3Smrg sizeof(uint32_t))); 1291e88f27b3Smrg if (!properties.props_ptr) 1292e88f27b3Smrg goto err_allocs; 1293e88f27b3Smrg properties.prop_values_ptr = VOID2U64(drmMalloc(count * 1294e88f27b3Smrg sizeof(uint64_t))); 1295e88f27b3Smrg if (!properties.prop_values_ptr) 1296e88f27b3Smrg goto err_allocs; 1297e88f27b3Smrg } 1298e88f27b3Smrg 1299e88f27b3Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties)) 1300e88f27b3Smrg goto err_allocs; 1301e88f27b3Smrg 1302e88f27b3Smrg if (count < properties.count_props) { 1303e88f27b3Smrg drmFree(U642VOID(properties.props_ptr)); 1304e88f27b3Smrg drmFree(U642VOID(properties.prop_values_ptr)); 1305e88f27b3Smrg goto retry; 1306e88f27b3Smrg } 1307e88f27b3Smrg count = properties.count_props; 1308e88f27b3Smrg 1309e88f27b3Smrg ret = drmMalloc(sizeof(*ret)); 1310e88f27b3Smrg if (!ret) 1311e88f27b3Smrg goto err_allocs; 1312e88f27b3Smrg 1313e88f27b3Smrg ret->count_props = count; 1314e88f27b3Smrg ret->props = drmAllocCpy(U642VOID(properties.props_ptr), 1315e88f27b3Smrg count, sizeof(uint32_t)); 1316e88f27b3Smrg ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr), 1317e88f27b3Smrg count, sizeof(uint64_t)); 1318e88f27b3Smrg if (ret->count_props && (!ret->props || !ret->prop_values)) { 1319e88f27b3Smrg drmFree(ret->props); 1320e88f27b3Smrg drmFree(ret->prop_values); 1321e88f27b3Smrg drmFree(ret); 1322e88f27b3Smrg ret = NULL; 1323e88f27b3Smrg } 1324e88f27b3Smrg 1325e88f27b3Smrgerr_allocs: 1326e88f27b3Smrg drmFree(U642VOID(properties.props_ptr)); 1327e88f27b3Smrg drmFree(U642VOID(properties.prop_values_ptr)); 1328e88f27b3Smrg return ret; 1329e88f27b3Smrg} 1330e88f27b3Smrg 13316260e5d5Smrgdrm_public void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr) 1332e88f27b3Smrg{ 1333e88f27b3Smrg if (!ptr) 1334e88f27b3Smrg return; 1335e88f27b3Smrg drmFree(ptr->props); 1336e88f27b3Smrg drmFree(ptr->prop_values); 1337e88f27b3Smrg drmFree(ptr); 1338e88f27b3Smrg} 1339e88f27b3Smrg 13406260e5d5Smrgdrm_public int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, 1341e88f27b3Smrg uint32_t property_id, uint64_t value) 1342e88f27b3Smrg{ 1343e88f27b3Smrg struct drm_mode_obj_set_property prop; 1344e88f27b3Smrg 1345424e9256Smrg memclear(prop); 1346e88f27b3Smrg prop.value = value; 1347e88f27b3Smrg prop.prop_id = property_id; 1348e88f27b3Smrg prop.obj_id = object_id; 1349e88f27b3Smrg prop.obj_type = object_type; 1350e88f27b3Smrg 1351e88f27b3Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); 1352e88f27b3Smrg} 1353424e9256Smrg 1354424e9256Smrgtypedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, *drmModeAtomicReqItemPtr; 1355424e9256Smrg 1356424e9256Smrgstruct _drmModeAtomicReqItem { 1357424e9256Smrg uint32_t object_id; 1358424e9256Smrg uint32_t property_id; 1359424e9256Smrg uint64_t value; 136050027b5bSmrg uint32_t cursor; 1361424e9256Smrg}; 1362424e9256Smrg 1363424e9256Smrgstruct _drmModeAtomicReq { 1364424e9256Smrg uint32_t cursor; 1365424e9256Smrg uint32_t size_items; 1366424e9256Smrg drmModeAtomicReqItemPtr items; 1367424e9256Smrg}; 1368424e9256Smrg 13696260e5d5Smrgdrm_public drmModeAtomicReqPtr drmModeAtomicAlloc(void) 1370424e9256Smrg{ 1371424e9256Smrg drmModeAtomicReqPtr req; 1372424e9256Smrg 1373424e9256Smrg req = drmMalloc(sizeof *req); 1374424e9256Smrg if (!req) 1375424e9256Smrg return NULL; 1376424e9256Smrg 1377424e9256Smrg req->items = NULL; 1378424e9256Smrg req->cursor = 0; 1379424e9256Smrg req->size_items = 0; 1380424e9256Smrg 1381424e9256Smrg return req; 1382424e9256Smrg} 1383424e9256Smrg 138450027b5bSmrgdrm_public drmModeAtomicReqPtr drmModeAtomicDuplicate(const drmModeAtomicReqPtr old) 1385424e9256Smrg{ 1386424e9256Smrg drmModeAtomicReqPtr new; 1387424e9256Smrg 1388fe517fc9Smrg if (!old) 1389fe517fc9Smrg return NULL; 1390fe517fc9Smrg 1391424e9256Smrg new = drmMalloc(sizeof *new); 1392424e9256Smrg if (!new) 1393424e9256Smrg return NULL; 1394424e9256Smrg 1395424e9256Smrg new->cursor = old->cursor; 1396424e9256Smrg new->size_items = old->size_items; 1397424e9256Smrg 1398424e9256Smrg if (old->size_items) { 1399424e9256Smrg new->items = drmMalloc(old->size_items * sizeof(*new->items)); 1400424e9256Smrg if (!new->items) { 1401424e9256Smrg free(new); 1402424e9256Smrg return NULL; 1403424e9256Smrg } 1404424e9256Smrg memcpy(new->items, old->items, 1405bf6cc7dcSmrg old->cursor * sizeof(*new->items)); 1406424e9256Smrg } else { 1407424e9256Smrg new->items = NULL; 1408424e9256Smrg } 1409424e9256Smrg 1410424e9256Smrg return new; 1411424e9256Smrg} 1412424e9256Smrg 14136260e5d5Smrgdrm_public int drmModeAtomicMerge(drmModeAtomicReqPtr base, 141450027b5bSmrg const drmModeAtomicReqPtr augment) 1415424e9256Smrg{ 141650027b5bSmrg uint32_t i; 141750027b5bSmrg 1418fe517fc9Smrg if (!base) 1419fe517fc9Smrg return -EINVAL; 1420fe517fc9Smrg 1421424e9256Smrg if (!augment || augment->cursor == 0) 1422424e9256Smrg return 0; 1423424e9256Smrg 1424424e9256Smrg if (base->cursor + augment->cursor >= base->size_items) { 1425424e9256Smrg drmModeAtomicReqItemPtr new; 1426424e9256Smrg int saved_size = base->size_items; 1427424e9256Smrg 1428424e9256Smrg base->size_items = base->cursor + augment->cursor; 1429424e9256Smrg new = realloc(base->items, 1430424e9256Smrg base->size_items * sizeof(*base->items)); 1431424e9256Smrg if (!new) { 1432424e9256Smrg base->size_items = saved_size; 1433424e9256Smrg return -ENOMEM; 1434424e9256Smrg } 1435424e9256Smrg base->items = new; 1436424e9256Smrg } 1437424e9256Smrg 1438424e9256Smrg memcpy(&base->items[base->cursor], augment->items, 1439424e9256Smrg augment->cursor * sizeof(*augment->items)); 144050027b5bSmrg for (i = base->cursor; i < base->cursor + augment->cursor; i++) 144150027b5bSmrg base->items[i].cursor = i; 1442424e9256Smrg base->cursor += augment->cursor; 1443424e9256Smrg 1444424e9256Smrg return 0; 1445424e9256Smrg} 1446424e9256Smrg 144750027b5bSmrgdrm_public int drmModeAtomicGetCursor(const drmModeAtomicReqPtr req) 1448424e9256Smrg{ 1449fe517fc9Smrg if (!req) 1450fe517fc9Smrg return -EINVAL; 1451424e9256Smrg return req->cursor; 1452424e9256Smrg} 1453424e9256Smrg 14546260e5d5Smrgdrm_public void drmModeAtomicSetCursor(drmModeAtomicReqPtr req, int cursor) 1455424e9256Smrg{ 1456fe517fc9Smrg if (req) 1457fe517fc9Smrg req->cursor = cursor; 1458424e9256Smrg} 1459424e9256Smrg 14606260e5d5Smrgdrm_public int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, 14616260e5d5Smrg uint32_t object_id, 14626260e5d5Smrg uint32_t property_id, 14636260e5d5Smrg uint64_t value) 1464424e9256Smrg{ 1465fe517fc9Smrg if (!req) 1466fe517fc9Smrg return -EINVAL; 1467fe517fc9Smrg 14686260e5d5Smrg if (object_id == 0 || property_id == 0) 14696260e5d5Smrg return -EINVAL; 14706260e5d5Smrg 1471424e9256Smrg if (req->cursor >= req->size_items) { 1472bf6cc7dcSmrg const uint32_t item_size_inc = getpagesize() / sizeof(*req->items); 1473424e9256Smrg drmModeAtomicReqItemPtr new; 1474424e9256Smrg 1475bf6cc7dcSmrg req->size_items += item_size_inc; 1476424e9256Smrg new = realloc(req->items, req->size_items * sizeof(*req->items)); 1477424e9256Smrg if (!new) { 1478bf6cc7dcSmrg req->size_items -= item_size_inc; 1479424e9256Smrg return -ENOMEM; 1480424e9256Smrg } 1481424e9256Smrg req->items = new; 1482424e9256Smrg } 1483424e9256Smrg 1484424e9256Smrg req->items[req->cursor].object_id = object_id; 1485424e9256Smrg req->items[req->cursor].property_id = property_id; 1486424e9256Smrg req->items[req->cursor].value = value; 148750027b5bSmrg req->items[req->cursor].cursor = req->cursor; 1488424e9256Smrg req->cursor++; 1489424e9256Smrg 1490424e9256Smrg return req->cursor; 1491424e9256Smrg} 1492424e9256Smrg 14936260e5d5Smrgdrm_public void drmModeAtomicFree(drmModeAtomicReqPtr req) 1494424e9256Smrg{ 1495424e9256Smrg if (!req) 1496424e9256Smrg return; 1497424e9256Smrg 1498424e9256Smrg if (req->items) 1499424e9256Smrg drmFree(req->items); 1500424e9256Smrg drmFree(req); 1501424e9256Smrg} 1502424e9256Smrg 1503424e9256Smrgstatic int sort_req_list(const void *misc, const void *other) 1504424e9256Smrg{ 1505424e9256Smrg const drmModeAtomicReqItem *first = misc; 1506424e9256Smrg const drmModeAtomicReqItem *second = other; 1507424e9256Smrg 150850027b5bSmrg if (first->object_id != second->object_id) 150950027b5bSmrg return first->object_id - second->object_id; 151050027b5bSmrg else if (first->property_id != second->property_id) 151150027b5bSmrg return first->property_id - second->property_id; 1512424e9256Smrg else 151350027b5bSmrg return first->cursor - second->cursor; 1514424e9256Smrg} 1515424e9256Smrg 151650027b5bSmrgdrm_public int drmModeAtomicCommit(int fd, const drmModeAtomicReqPtr req, 15176260e5d5Smrg uint32_t flags, void *user_data) 1518424e9256Smrg{ 1519fe517fc9Smrg drmModeAtomicReqPtr sorted; 1520424e9256Smrg struct drm_mode_atomic atomic; 1521424e9256Smrg uint32_t *objs_ptr = NULL; 1522424e9256Smrg uint32_t *count_props_ptr = NULL; 1523424e9256Smrg uint32_t *props_ptr = NULL; 1524424e9256Smrg uint64_t *prop_values_ptr = NULL; 1525424e9256Smrg uint32_t last_obj_id = 0; 1526424e9256Smrg uint32_t i; 1527424e9256Smrg int obj_idx = -1; 1528424e9256Smrg int ret = -1; 1529424e9256Smrg 1530fe517fc9Smrg if (!req) 1531fe517fc9Smrg return -EINVAL; 1532fe517fc9Smrg 1533fe517fc9Smrg if (req->cursor == 0) 1534fe517fc9Smrg return 0; 1535fe517fc9Smrg 1536fe517fc9Smrg sorted = drmModeAtomicDuplicate(req); 1537fe517fc9Smrg if (sorted == NULL) 1538424e9256Smrg return -ENOMEM; 1539424e9256Smrg 1540424e9256Smrg memclear(atomic); 1541424e9256Smrg 1542424e9256Smrg /* Sort the list by object ID, then by property ID. */ 1543424e9256Smrg qsort(sorted->items, sorted->cursor, sizeof(*sorted->items), 1544424e9256Smrg sort_req_list); 1545424e9256Smrg 1546424e9256Smrg /* Now the list is sorted, eliminate duplicate property sets. */ 1547424e9256Smrg for (i = 0; i < sorted->cursor; i++) { 1548424e9256Smrg if (sorted->items[i].object_id != last_obj_id) { 1549424e9256Smrg atomic.count_objs++; 1550424e9256Smrg last_obj_id = sorted->items[i].object_id; 1551424e9256Smrg } 1552424e9256Smrg 1553424e9256Smrg if (i == sorted->cursor - 1) 1554424e9256Smrg continue; 1555424e9256Smrg 1556424e9256Smrg if (sorted->items[i].object_id != sorted->items[i + 1].object_id || 1557424e9256Smrg sorted->items[i].property_id != sorted->items[i + 1].property_id) 1558424e9256Smrg continue; 1559424e9256Smrg 1560424e9256Smrg memmove(&sorted->items[i], &sorted->items[i + 1], 1561424e9256Smrg (sorted->cursor - i - 1) * sizeof(*sorted->items)); 1562424e9256Smrg sorted->cursor--; 1563424e9256Smrg } 1564424e9256Smrg 156550027b5bSmrg for (i = 0; i < sorted->cursor; i++) 156650027b5bSmrg sorted->items[i].cursor = i; 156750027b5bSmrg 1568424e9256Smrg objs_ptr = drmMalloc(atomic.count_objs * sizeof objs_ptr[0]); 1569424e9256Smrg if (!objs_ptr) { 1570424e9256Smrg errno = ENOMEM; 1571424e9256Smrg goto out; 1572424e9256Smrg } 1573424e9256Smrg 1574424e9256Smrg count_props_ptr = drmMalloc(atomic.count_objs * sizeof count_props_ptr[0]); 1575424e9256Smrg if (!count_props_ptr) { 1576424e9256Smrg errno = ENOMEM; 1577424e9256Smrg goto out; 1578424e9256Smrg } 1579424e9256Smrg 1580424e9256Smrg props_ptr = drmMalloc(sorted->cursor * sizeof props_ptr[0]); 1581424e9256Smrg if (!props_ptr) { 1582424e9256Smrg errno = ENOMEM; 1583424e9256Smrg goto out; 1584424e9256Smrg } 1585424e9256Smrg 1586424e9256Smrg prop_values_ptr = drmMalloc(sorted->cursor * sizeof prop_values_ptr[0]); 1587424e9256Smrg if (!prop_values_ptr) { 1588424e9256Smrg errno = ENOMEM; 1589424e9256Smrg goto out; 1590424e9256Smrg } 1591424e9256Smrg 1592424e9256Smrg for (i = 0, last_obj_id = 0; i < sorted->cursor; i++) { 1593424e9256Smrg if (sorted->items[i].object_id != last_obj_id) { 1594424e9256Smrg obj_idx++; 1595424e9256Smrg objs_ptr[obj_idx] = sorted->items[i].object_id; 1596424e9256Smrg last_obj_id = objs_ptr[obj_idx]; 1597424e9256Smrg } 1598424e9256Smrg 1599424e9256Smrg count_props_ptr[obj_idx]++; 1600424e9256Smrg props_ptr[i] = sorted->items[i].property_id; 1601424e9256Smrg prop_values_ptr[i] = sorted->items[i].value; 1602424e9256Smrg 1603424e9256Smrg } 1604424e9256Smrg 1605424e9256Smrg atomic.flags = flags; 1606424e9256Smrg atomic.objs_ptr = VOID2U64(objs_ptr); 1607424e9256Smrg atomic.count_props_ptr = VOID2U64(count_props_ptr); 1608424e9256Smrg atomic.props_ptr = VOID2U64(props_ptr); 1609424e9256Smrg atomic.prop_values_ptr = VOID2U64(prop_values_ptr); 1610424e9256Smrg atomic.user_data = VOID2U64(user_data); 1611424e9256Smrg 1612424e9256Smrg ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic); 1613424e9256Smrg 1614424e9256Smrgout: 1615424e9256Smrg drmFree(objs_ptr); 1616424e9256Smrg drmFree(count_props_ptr); 1617424e9256Smrg drmFree(props_ptr); 1618424e9256Smrg drmFree(prop_values_ptr); 1619424e9256Smrg drmModeAtomicFree(sorted); 1620424e9256Smrg 1621424e9256Smrg return ret; 1622424e9256Smrg} 1623424e9256Smrg 16246260e5d5Smrgdrm_public int 16256260e5d5SmrgdrmModeCreatePropertyBlob(int fd, const void *data, size_t length, 16266260e5d5Smrg uint32_t *id) 1627424e9256Smrg{ 1628424e9256Smrg struct drm_mode_create_blob create; 1629424e9256Smrg int ret; 1630424e9256Smrg 1631424e9256Smrg if (length >= 0xffffffff) 1632424e9256Smrg return -ERANGE; 1633424e9256Smrg 1634424e9256Smrg memclear(create); 1635424e9256Smrg 1636424e9256Smrg create.length = length; 1637424e9256Smrg create.data = (uintptr_t) data; 1638424e9256Smrg create.blob_id = 0; 1639424e9256Smrg *id = 0; 1640424e9256Smrg 1641424e9256Smrg ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &create); 1642424e9256Smrg if (ret != 0) 1643424e9256Smrg return ret; 1644424e9256Smrg 1645424e9256Smrg *id = create.blob_id; 1646424e9256Smrg return 0; 1647424e9256Smrg} 1648424e9256Smrg 16496260e5d5Smrgdrm_public int 1650424e9256SmrgdrmModeDestroyPropertyBlob(int fd, uint32_t id) 1651424e9256Smrg{ 1652424e9256Smrg struct drm_mode_destroy_blob destroy; 1653424e9256Smrg 1654424e9256Smrg memclear(destroy); 1655424e9256Smrg destroy.blob_id = id; 1656424e9256Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy); 1657424e9256Smrg} 16582b90624aSmrg 16596260e5d5Smrgdrm_public int 16606260e5d5SmrgdrmModeCreateLease(int fd, const uint32_t *objects, int num_objects, int flags, 16616260e5d5Smrg uint32_t *lessee_id) 16622b90624aSmrg{ 16632b90624aSmrg struct drm_mode_create_lease create; 16642b90624aSmrg int ret; 16652b90624aSmrg 16662b90624aSmrg memclear(create); 16672b90624aSmrg create.object_ids = (uintptr_t) objects; 16682b90624aSmrg create.object_count = num_objects; 16692b90624aSmrg create.flags = flags; 16702b90624aSmrg 16712b90624aSmrg ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_CREATE_LEASE, &create); 16722b90624aSmrg if (ret == 0) { 16732b90624aSmrg *lessee_id = create.lessee_id; 16742b90624aSmrg return create.fd; 16752b90624aSmrg } 16762b90624aSmrg return -errno; 16772b90624aSmrg} 16782b90624aSmrg 16796260e5d5Smrgdrm_public drmModeLesseeListPtr 16802b90624aSmrgdrmModeListLessees(int fd) 16812b90624aSmrg{ 16822b90624aSmrg struct drm_mode_list_lessees list; 16832b90624aSmrg uint32_t count; 16842b90624aSmrg drmModeLesseeListPtr ret; 16852b90624aSmrg 16862b90624aSmrg memclear(list); 16872b90624aSmrg 16882b90624aSmrg if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list)) 16892b90624aSmrg return NULL; 16902b90624aSmrg 16912b90624aSmrg count = list.count_lessees; 16922b90624aSmrg ret = drmMalloc(sizeof (drmModeLesseeListRes) + count * sizeof (ret->lessees[0])); 16932b90624aSmrg if (!ret) 16942b90624aSmrg return NULL; 16952b90624aSmrg 16962b90624aSmrg list.lessees_ptr = VOID2U64(&ret->lessees[0]); 16972b90624aSmrg if (DRM_IOCTL(fd, DRM_IOCTL_MODE_LIST_LESSEES, &list)) { 16982b90624aSmrg drmFree(ret); 16992b90624aSmrg return NULL; 17002b90624aSmrg } 17012b90624aSmrg 17022b90624aSmrg ret->count = count; 17032b90624aSmrg return ret; 17042b90624aSmrg} 17052b90624aSmrg 17066260e5d5Smrgdrm_public drmModeObjectListPtr 17072b90624aSmrgdrmModeGetLease(int fd) 17082b90624aSmrg{ 17092b90624aSmrg struct drm_mode_get_lease get; 17102b90624aSmrg uint32_t count; 17112b90624aSmrg drmModeObjectListPtr ret; 17122b90624aSmrg 17132b90624aSmrg memclear(get); 17142b90624aSmrg 17152b90624aSmrg if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get)) 17162b90624aSmrg return NULL; 17172b90624aSmrg 17182b90624aSmrg count = get.count_objects; 17192b90624aSmrg ret = drmMalloc(sizeof (drmModeObjectListRes) + count * sizeof (ret->objects[0])); 17202b90624aSmrg if (!ret) 17212b90624aSmrg return NULL; 17222b90624aSmrg 17232b90624aSmrg get.objects_ptr = VOID2U64(&ret->objects[0]); 17242b90624aSmrg if (DRM_IOCTL(fd, DRM_IOCTL_MODE_GET_LEASE, &get)) { 17252b90624aSmrg drmFree(ret); 17262b90624aSmrg return NULL; 17272b90624aSmrg } 17282b90624aSmrg 17292b90624aSmrg ret->count = count; 17302b90624aSmrg return ret; 17312b90624aSmrg} 17322b90624aSmrg 17336260e5d5Smrgdrm_public int 17342b90624aSmrgdrmModeRevokeLease(int fd, uint32_t lessee_id) 17352b90624aSmrg{ 17362b90624aSmrg struct drm_mode_revoke_lease revoke; 17372b90624aSmrg int ret; 17382b90624aSmrg 17392b90624aSmrg memclear(revoke); 17402b90624aSmrg 17412b90624aSmrg revoke.lessee_id = lessee_id; 17422b90624aSmrg 17432b90624aSmrg ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_REVOKE_LEASE, &revoke); 17442b90624aSmrg if (ret == 0) 17452b90624aSmrg return 0; 17462b90624aSmrg return -errno; 17472b90624aSmrg} 174887bf8e7cSmrg 174987bf8e7cSmrgdrm_public drmModeFB2Ptr 175087bf8e7cSmrgdrmModeGetFB2(int fd, uint32_t fb_id) 175187bf8e7cSmrg{ 175287bf8e7cSmrg struct drm_mode_fb_cmd2 get = { 175387bf8e7cSmrg .fb_id = fb_id, 175487bf8e7cSmrg }; 175587bf8e7cSmrg drmModeFB2Ptr ret; 175687bf8e7cSmrg int err; 175787bf8e7cSmrg 175887bf8e7cSmrg err = DRM_IOCTL(fd, DRM_IOCTL_MODE_GETFB2, &get); 175987bf8e7cSmrg if (err != 0) 176087bf8e7cSmrg return NULL; 176187bf8e7cSmrg 176287bf8e7cSmrg ret = drmMalloc(sizeof(drmModeFB2)); 176387bf8e7cSmrg if (!ret) 176487bf8e7cSmrg return NULL; 176587bf8e7cSmrg 176687bf8e7cSmrg ret->fb_id = fb_id; 176787bf8e7cSmrg ret->width = get.width; 176887bf8e7cSmrg ret->height = get.height; 176987bf8e7cSmrg ret->pixel_format = get.pixel_format; 177087bf8e7cSmrg ret->flags = get.flags; 177187bf8e7cSmrg ret->modifier = get.modifier[0]; 177287bf8e7cSmrg memcpy(ret->handles, get.handles, sizeof(uint32_t) * 4); 177387bf8e7cSmrg memcpy(ret->pitches, get.pitches, sizeof(uint32_t) * 4); 177487bf8e7cSmrg memcpy(ret->offsets, get.offsets, sizeof(uint32_t) * 4); 177587bf8e7cSmrg 177687bf8e7cSmrg return ret; 177787bf8e7cSmrg} 177887bf8e7cSmrg 177987bf8e7cSmrgdrm_public void drmModeFreeFB2(drmModeFB2Ptr ptr) 178087bf8e7cSmrg{ 178187bf8e7cSmrg drmFree(ptr); 178287bf8e7cSmrg} 178350027b5bSmrg 178450027b5bSmrgdrm_public const char * 178550027b5bSmrgdrmModeGetConnectorTypeName(uint32_t connector_type) 178650027b5bSmrg{ 178750027b5bSmrg /* Keep the strings in sync with the kernel's drm_connector_enum_list in 178850027b5bSmrg * drm_connector.c. */ 178950027b5bSmrg switch (connector_type) { 179050027b5bSmrg case DRM_MODE_CONNECTOR_Unknown: 179150027b5bSmrg return "Unknown"; 179250027b5bSmrg case DRM_MODE_CONNECTOR_VGA: 179350027b5bSmrg return "VGA"; 179450027b5bSmrg case DRM_MODE_CONNECTOR_DVII: 179550027b5bSmrg return "DVI-I"; 179650027b5bSmrg case DRM_MODE_CONNECTOR_DVID: 179750027b5bSmrg return "DVI-D"; 179850027b5bSmrg case DRM_MODE_CONNECTOR_DVIA: 179950027b5bSmrg return "DVI-A"; 180050027b5bSmrg case DRM_MODE_CONNECTOR_Composite: 180150027b5bSmrg return "Composite"; 180250027b5bSmrg case DRM_MODE_CONNECTOR_SVIDEO: 180350027b5bSmrg return "SVIDEO"; 180450027b5bSmrg case DRM_MODE_CONNECTOR_LVDS: 180550027b5bSmrg return "LVDS"; 180650027b5bSmrg case DRM_MODE_CONNECTOR_Component: 180750027b5bSmrg return "Component"; 180850027b5bSmrg case DRM_MODE_CONNECTOR_9PinDIN: 180950027b5bSmrg return "DIN"; 181050027b5bSmrg case DRM_MODE_CONNECTOR_DisplayPort: 181150027b5bSmrg return "DP"; 181250027b5bSmrg case DRM_MODE_CONNECTOR_HDMIA: 181350027b5bSmrg return "HDMI-A"; 181450027b5bSmrg case DRM_MODE_CONNECTOR_HDMIB: 181550027b5bSmrg return "HDMI-B"; 181650027b5bSmrg case DRM_MODE_CONNECTOR_TV: 181750027b5bSmrg return "TV"; 181850027b5bSmrg case DRM_MODE_CONNECTOR_eDP: 181950027b5bSmrg return "eDP"; 182050027b5bSmrg case DRM_MODE_CONNECTOR_VIRTUAL: 182150027b5bSmrg return "Virtual"; 182250027b5bSmrg case DRM_MODE_CONNECTOR_DSI: 182350027b5bSmrg return "DSI"; 182450027b5bSmrg case DRM_MODE_CONNECTOR_DPI: 182550027b5bSmrg return "DPI"; 182650027b5bSmrg case DRM_MODE_CONNECTOR_WRITEBACK: 182750027b5bSmrg return "Writeback"; 182850027b5bSmrg case DRM_MODE_CONNECTOR_SPI: 182950027b5bSmrg return "SPI"; 183050027b5bSmrg case DRM_MODE_CONNECTOR_USB: 183150027b5bSmrg return "USB"; 183250027b5bSmrg default: 183350027b5bSmrg return NULL; 183450027b5bSmrg } 183550027b5bSmrg} 18363b115362Smrg 18373b115362Smrgdrm_public int 18383b115362SmrgdrmModeCreateDumbBuffer(int fd, uint32_t width, uint32_t height, uint32_t bpp, 18393b115362Smrg uint32_t flags, uint32_t *handle, uint32_t *pitch, 18403b115362Smrg uint64_t *size) 18413b115362Smrg{ 18423b115362Smrg int ret; 18433b115362Smrg struct drm_mode_create_dumb create = { 18443b115362Smrg .width = width, 18453b115362Smrg .height = height, 18463b115362Smrg .bpp = bpp, 18473b115362Smrg .flags = flags, 18483b115362Smrg }; 18493b115362Smrg 18503b115362Smrg ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); 18513b115362Smrg if (ret != 0) 18523b115362Smrg return ret; 18533b115362Smrg 18543b115362Smrg *handle = create.handle; 18553b115362Smrg *pitch = create.pitch; 18563b115362Smrg *size = create.size; 18573b115362Smrg return 0; 18583b115362Smrg} 18593b115362Smrg 18603b115362Smrgdrm_public int 18613b115362SmrgdrmModeDestroyDumbBuffer(int fd, uint32_t handle) 18623b115362Smrg{ 18633b115362Smrg struct drm_mode_destroy_dumb destroy = { 18643b115362Smrg .handle = handle, 18653b115362Smrg }; 18663b115362Smrg 18673b115362Smrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy); 18683b115362Smrg} 18693b115362Smrg 18703b115362Smrgdrm_public int 18713b115362SmrgdrmModeMapDumbBuffer(int fd, uint32_t handle, uint64_t *offset) 18723b115362Smrg{ 18733b115362Smrg int ret; 18743b115362Smrg struct drm_mode_map_dumb map = { 18753b115362Smrg .handle = handle, 18763b115362Smrg }; 18773b115362Smrg 18783b115362Smrg ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_MAP_DUMB, &map); 18793b115362Smrg if (ret != 0) 18803b115362Smrg return ret; 18813b115362Smrg 18823b115362Smrg *offset = map.offset; 18833b115362Smrg return 0; 18843b115362Smrg} 1885