xf86drmMode.c revision d049871a
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 4422944501Smrg#include "xf86drmMode.h" 4522944501Smrg#include "xf86drm.h" 4622944501Smrg#include <drm.h> 4722944501Smrg#include <string.h> 4822944501Smrg#include <dirent.h> 4922944501Smrg#include <unistd.h> 5022944501Smrg#include <errno.h> 5122944501Smrg 5222944501Smrg#define U642VOID(x) ((void *)(unsigned long)(x)) 5322944501Smrg#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) 5422944501Smrg 55d049871aSmrgstatic inline DRM_IOCTL(int fd, int cmd, void *arg) 56d049871aSmrg{ 57d049871aSmrg int ret = drmIoctl(fd, cmd, arg); 58d049871aSmrg return ret < 0 ? -errno : ret; 59d049871aSmrg} 60d049871aSmrg 6122944501Smrg/* 6222944501Smrg * Util functions 6322944501Smrg */ 6422944501Smrg 6522944501Smrgvoid* drmAllocCpy(void *array, int count, int entry_size) 6622944501Smrg{ 6722944501Smrg char *r; 6822944501Smrg int i; 6922944501Smrg 7022944501Smrg if (!count || !array || !entry_size) 7122944501Smrg return 0; 7222944501Smrg 7322944501Smrg if (!(r = drmMalloc(count*entry_size))) 7422944501Smrg return 0; 7522944501Smrg 7622944501Smrg for (i = 0; i < count; i++) 7722944501Smrg memcpy(r+(entry_size*i), array+(entry_size*i), entry_size); 7822944501Smrg 7922944501Smrg return r; 8022944501Smrg} 8122944501Smrg 8222944501Smrg/* 8322944501Smrg * A couple of free functions. 8422944501Smrg */ 8522944501Smrg 8622944501Smrgvoid drmModeFreeModeInfo(drmModeModeInfoPtr ptr) 8722944501Smrg{ 8822944501Smrg if (!ptr) 8922944501Smrg return; 9022944501Smrg 9122944501Smrg drmFree(ptr); 9222944501Smrg} 9322944501Smrg 9422944501Smrgvoid drmModeFreeResources(drmModeResPtr ptr) 9522944501Smrg{ 9622944501Smrg if (!ptr) 9722944501Smrg return; 9822944501Smrg 9922944501Smrg drmFree(ptr); 10022944501Smrg 10122944501Smrg} 10222944501Smrg 10322944501Smrgvoid drmModeFreeFB(drmModeFBPtr ptr) 10422944501Smrg{ 10522944501Smrg if (!ptr) 10622944501Smrg return; 10722944501Smrg 10822944501Smrg /* we might add more frees later. */ 10922944501Smrg drmFree(ptr); 11022944501Smrg} 11122944501Smrg 11222944501Smrgvoid drmModeFreeCrtc(drmModeCrtcPtr ptr) 11322944501Smrg{ 11422944501Smrg if (!ptr) 11522944501Smrg return; 11622944501Smrg 11722944501Smrg drmFree(ptr); 11822944501Smrg 11922944501Smrg} 12022944501Smrg 12122944501Smrgvoid drmModeFreeConnector(drmModeConnectorPtr ptr) 12222944501Smrg{ 12322944501Smrg if (!ptr) 12422944501Smrg return; 12522944501Smrg 12622944501Smrg drmFree(ptr->encoders); 12722944501Smrg drmFree(ptr->prop_values); 12822944501Smrg drmFree(ptr->props); 12922944501Smrg drmFree(ptr->modes); 13022944501Smrg drmFree(ptr); 13122944501Smrg 13222944501Smrg} 13322944501Smrg 13422944501Smrgvoid drmModeFreeEncoder(drmModeEncoderPtr ptr) 13522944501Smrg{ 13622944501Smrg drmFree(ptr); 13722944501Smrg} 13822944501Smrg 13922944501Smrg/* 14022944501Smrg * ModeSetting functions. 14122944501Smrg */ 14222944501Smrg 14322944501SmrgdrmModeResPtr drmModeGetResources(int fd) 14422944501Smrg{ 14522944501Smrg struct drm_mode_card_res res, counts; 14622944501Smrg drmModeResPtr r = 0; 14722944501Smrg 14822944501Smrgretry: 14922944501Smrg memset(&res, 0, sizeof(struct drm_mode_card_res)); 15022944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 15122944501Smrg return 0; 15222944501Smrg 15322944501Smrg counts = res; 15422944501Smrg 15522944501Smrg if (res.count_fbs) { 15622944501Smrg res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t))); 15722944501Smrg if (!res.fb_id_ptr) 15822944501Smrg goto err_allocs; 15922944501Smrg } 16022944501Smrg if (res.count_crtcs) { 16122944501Smrg res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t))); 16222944501Smrg if (!res.crtc_id_ptr) 16322944501Smrg goto err_allocs; 16422944501Smrg } 16522944501Smrg if (res.count_connectors) { 16622944501Smrg res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t))); 16722944501Smrg if (!res.connector_id_ptr) 16822944501Smrg goto err_allocs; 16922944501Smrg } 17022944501Smrg if (res.count_encoders) { 17122944501Smrg res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t))); 17222944501Smrg if (!res.encoder_id_ptr) 17322944501Smrg goto err_allocs; 17422944501Smrg } 17522944501Smrg 17622944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) 17722944501Smrg goto err_allocs; 17822944501Smrg 17922944501Smrg /* The number of available connectors and etc may have changed with a 18022944501Smrg * hotplug event in between the ioctls, in which case the field is 18122944501Smrg * silently ignored by the kernel. 18222944501Smrg */ 18322944501Smrg if (counts.count_fbs < res.count_fbs || 18422944501Smrg counts.count_crtcs < res.count_crtcs || 18522944501Smrg counts.count_connectors < res.count_connectors || 18622944501Smrg counts.count_encoders < res.count_encoders) 18722944501Smrg { 18822944501Smrg drmFree(U642VOID(res.fb_id_ptr)); 18922944501Smrg drmFree(U642VOID(res.crtc_id_ptr)); 19022944501Smrg drmFree(U642VOID(res.connector_id_ptr)); 19122944501Smrg drmFree(U642VOID(res.encoder_id_ptr)); 19222944501Smrg 19322944501Smrg goto retry; 19422944501Smrg } 19522944501Smrg 19622944501Smrg /* 19722944501Smrg * return 19822944501Smrg */ 19922944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 20022944501Smrg goto err_allocs; 20122944501Smrg 20222944501Smrg r->min_width = res.min_width; 20322944501Smrg r->max_width = res.max_width; 20422944501Smrg r->min_height = res.min_height; 20522944501Smrg r->max_height = res.max_height; 20622944501Smrg r->count_fbs = res.count_fbs; 20722944501Smrg r->count_crtcs = res.count_crtcs; 20822944501Smrg r->count_connectors = res.count_connectors; 20922944501Smrg r->count_encoders = res.count_encoders; 21022944501Smrg 21122944501Smrg r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t)); 21222944501Smrg r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t)); 21322944501Smrg r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t)); 21422944501Smrg r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t)); 21522944501Smrg if ((res.count_fbs && !r->fbs) || 21622944501Smrg (res.count_crtcs && !r->crtcs) || 21722944501Smrg (res.count_connectors && !r->connectors) || 21822944501Smrg (res.count_encoders && !r->encoders)) 21922944501Smrg { 22022944501Smrg drmFree(r->fbs); 22122944501Smrg drmFree(r->crtcs); 22222944501Smrg drmFree(r->connectors); 22322944501Smrg drmFree(r->encoders); 22422944501Smrg drmFree(r); 22522944501Smrg r = 0; 22622944501Smrg } 22722944501Smrg 22822944501Smrgerr_allocs: 22922944501Smrg drmFree(U642VOID(res.fb_id_ptr)); 23022944501Smrg drmFree(U642VOID(res.crtc_id_ptr)); 23122944501Smrg drmFree(U642VOID(res.connector_id_ptr)); 23222944501Smrg drmFree(U642VOID(res.encoder_id_ptr)); 23322944501Smrg 23422944501Smrg return r; 23522944501Smrg} 23622944501Smrg 23722944501Smrgint drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, 23822944501Smrg uint8_t bpp, uint32_t pitch, uint32_t bo_handle, 23922944501Smrg uint32_t *buf_id) 24022944501Smrg{ 24122944501Smrg struct drm_mode_fb_cmd f; 24222944501Smrg int ret; 24322944501Smrg 24422944501Smrg f.width = width; 24522944501Smrg f.height = height; 24622944501Smrg f.pitch = pitch; 24722944501Smrg f.bpp = bpp; 24822944501Smrg f.depth = depth; 24922944501Smrg f.handle = bo_handle; 25022944501Smrg 251d049871aSmrg if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f))) 25222944501Smrg return ret; 25322944501Smrg 25422944501Smrg *buf_id = f.fb_id; 25522944501Smrg return 0; 25622944501Smrg} 25722944501Smrg 25822944501Smrgint drmModeRmFB(int fd, uint32_t bufferId) 25922944501Smrg{ 260d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId); 26122944501Smrg 26222944501Smrg 26322944501Smrg} 26422944501Smrg 26522944501SmrgdrmModeFBPtr drmModeGetFB(int fd, uint32_t buf) 26622944501Smrg{ 26722944501Smrg struct drm_mode_fb_cmd info; 26822944501Smrg drmModeFBPtr r; 26922944501Smrg 27022944501Smrg info.fb_id = buf; 27122944501Smrg 27222944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info)) 27322944501Smrg return NULL; 27422944501Smrg 27522944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 27622944501Smrg return NULL; 27722944501Smrg 27822944501Smrg r->fb_id = info.fb_id; 27922944501Smrg r->width = info.width; 28022944501Smrg r->height = info.height; 28122944501Smrg r->pitch = info.pitch; 28222944501Smrg r->bpp = info.bpp; 28322944501Smrg r->handle = info.handle; 28422944501Smrg r->depth = info.depth; 28522944501Smrg 28622944501Smrg return r; 28722944501Smrg} 28822944501Smrg 28922944501Smrgint drmModeDirtyFB(int fd, uint32_t bufferId, 29022944501Smrg drmModeClipPtr clips, uint32_t num_clips) 29122944501Smrg{ 29222944501Smrg struct drm_mode_fb_dirty_cmd dirty = { 0 }; 29322944501Smrg 29422944501Smrg dirty.fb_id = bufferId; 29522944501Smrg dirty.clips_ptr = VOID2U64(clips); 29622944501Smrg dirty.num_clips = num_clips; 29722944501Smrg 298d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty); 29922944501Smrg} 30022944501Smrg 30122944501Smrg 30222944501Smrg/* 30322944501Smrg * Crtc functions 30422944501Smrg */ 30522944501Smrg 30622944501SmrgdrmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId) 30722944501Smrg{ 30822944501Smrg struct drm_mode_crtc crtc; 30922944501Smrg drmModeCrtcPtr r; 31022944501Smrg 31122944501Smrg crtc.crtc_id = crtcId; 31222944501Smrg 31322944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc)) 31422944501Smrg return 0; 31522944501Smrg 31622944501Smrg /* 31722944501Smrg * return 31822944501Smrg */ 31922944501Smrg 32022944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 32122944501Smrg return 0; 32222944501Smrg 32322944501Smrg r->crtc_id = crtc.crtc_id; 32422944501Smrg r->x = crtc.x; 32522944501Smrg r->y = crtc.y; 32622944501Smrg r->mode_valid = crtc.mode_valid; 32722944501Smrg if (r->mode_valid) 32822944501Smrg memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo)); 32922944501Smrg r->buffer_id = crtc.fb_id; 33022944501Smrg r->gamma_size = crtc.gamma_size; 33122944501Smrg return r; 33222944501Smrg} 33322944501Smrg 33422944501Smrg 33522944501Smrgint drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId, 33622944501Smrg uint32_t x, uint32_t y, uint32_t *connectors, int count, 33722944501Smrg drmModeModeInfoPtr mode) 33822944501Smrg{ 33922944501Smrg struct drm_mode_crtc crtc; 34022944501Smrg 34122944501Smrg crtc.x = x; 34222944501Smrg crtc.y = y; 34322944501Smrg crtc.crtc_id = crtcId; 34422944501Smrg crtc.fb_id = bufferId; 34522944501Smrg crtc.set_connectors_ptr = VOID2U64(connectors); 34622944501Smrg crtc.count_connectors = count; 34722944501Smrg if (mode) { 34822944501Smrg memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo)); 34922944501Smrg crtc.mode_valid = 1; 35022944501Smrg } else 35122944501Smrg crtc.mode_valid = 0; 35222944501Smrg 353d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc); 35422944501Smrg} 35522944501Smrg 35622944501Smrg/* 35722944501Smrg * Cursor manipulation 35822944501Smrg */ 35922944501Smrg 36022944501Smrgint drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height) 36122944501Smrg{ 36222944501Smrg struct drm_mode_cursor arg; 36322944501Smrg 36422944501Smrg arg.flags = DRM_MODE_CURSOR_BO; 36522944501Smrg arg.crtc_id = crtcId; 36622944501Smrg arg.width = width; 36722944501Smrg arg.height = height; 36822944501Smrg arg.handle = bo_handle; 36922944501Smrg 370d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 37122944501Smrg} 37222944501Smrg 37322944501Smrgint drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y) 37422944501Smrg{ 37522944501Smrg struct drm_mode_cursor arg; 37622944501Smrg 37722944501Smrg arg.flags = DRM_MODE_CURSOR_MOVE; 37822944501Smrg arg.crtc_id = crtcId; 37922944501Smrg arg.x = x; 38022944501Smrg arg.y = y; 38122944501Smrg 382d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg); 38322944501Smrg} 38422944501Smrg 38522944501Smrg/* 38622944501Smrg * Encoder get 38722944501Smrg */ 38822944501SmrgdrmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id) 38922944501Smrg{ 39022944501Smrg struct drm_mode_get_encoder enc; 39122944501Smrg drmModeEncoderPtr r = NULL; 39222944501Smrg 39322944501Smrg enc.encoder_id = encoder_id; 39422944501Smrg enc.encoder_type = 0; 39522944501Smrg enc.possible_crtcs = 0; 39622944501Smrg enc.possible_clones = 0; 39722944501Smrg 39822944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc)) 39922944501Smrg return 0; 40022944501Smrg 40122944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 40222944501Smrg return 0; 40322944501Smrg 40422944501Smrg r->encoder_id = enc.encoder_id; 40522944501Smrg r->crtc_id = enc.crtc_id; 40622944501Smrg r->encoder_type = enc.encoder_type; 40722944501Smrg r->possible_crtcs = enc.possible_crtcs; 40822944501Smrg r->possible_clones = enc.possible_clones; 40922944501Smrg 41022944501Smrg return r; 41122944501Smrg} 41222944501Smrg 41322944501Smrg/* 41422944501Smrg * Connector manipulation 41522944501Smrg */ 41622944501Smrg 41722944501SmrgdrmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) 41822944501Smrg{ 41922944501Smrg struct drm_mode_get_connector conn, counts; 42022944501Smrg drmModeConnectorPtr r = NULL; 42122944501Smrg 42222944501Smrgretry: 42322944501Smrg memset(&conn, 0, sizeof(struct drm_mode_get_connector)); 42422944501Smrg conn.connector_id = connector_id; 42522944501Smrg 42622944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 42722944501Smrg return 0; 42822944501Smrg 42922944501Smrg counts = conn; 43022944501Smrg 43122944501Smrg if (conn.count_props) { 43222944501Smrg conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t))); 43322944501Smrg if (!conn.props_ptr) 43422944501Smrg goto err_allocs; 43522944501Smrg conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t))); 43622944501Smrg if (!conn.prop_values_ptr) 43722944501Smrg goto err_allocs; 43822944501Smrg } 43922944501Smrg 44022944501Smrg if (conn.count_modes) { 44122944501Smrg conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo))); 44222944501Smrg if (!conn.modes_ptr) 44322944501Smrg goto err_allocs; 44422944501Smrg } 44522944501Smrg 44622944501Smrg if (conn.count_encoders) { 44722944501Smrg conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t))); 44822944501Smrg if (!conn.encoders_ptr) 44922944501Smrg goto err_allocs; 45022944501Smrg } 45122944501Smrg 45222944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) 45322944501Smrg goto err_allocs; 45422944501Smrg 45522944501Smrg /* The number of available connectors and etc may have changed with a 45622944501Smrg * hotplug event in between the ioctls, in which case the field is 45722944501Smrg * silently ignored by the kernel. 45822944501Smrg */ 45922944501Smrg if (counts.count_props < conn.count_props || 46022944501Smrg counts.count_modes < conn.count_modes || 46122944501Smrg counts.count_encoders < conn.count_encoders) { 46222944501Smrg drmFree(U642VOID(conn.props_ptr)); 46322944501Smrg drmFree(U642VOID(conn.prop_values_ptr)); 46422944501Smrg drmFree(U642VOID(conn.modes_ptr)); 46522944501Smrg drmFree(U642VOID(conn.encoders_ptr)); 46622944501Smrg 46722944501Smrg goto retry; 46822944501Smrg } 46922944501Smrg 47022944501Smrg if(!(r = drmMalloc(sizeof(*r)))) { 47122944501Smrg goto err_allocs; 47222944501Smrg } 47322944501Smrg 47422944501Smrg r->connector_id = conn.connector_id; 47522944501Smrg r->encoder_id = conn.encoder_id; 47622944501Smrg r->connection = conn.connection; 47722944501Smrg r->mmWidth = conn.mm_width; 47822944501Smrg r->mmHeight = conn.mm_height; 47922944501Smrg /* convert subpixel from kernel to userspace */ 48022944501Smrg r->subpixel = conn.subpixel + 1; 48122944501Smrg r->count_modes = conn.count_modes; 48222944501Smrg r->count_props = conn.count_props; 48322944501Smrg r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t)); 48422944501Smrg r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t)); 48522944501Smrg r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo)); 48622944501Smrg r->count_encoders = conn.count_encoders; 48722944501Smrg r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t)); 48822944501Smrg r->connector_type = conn.connector_type; 48922944501Smrg r->connector_type_id = conn.connector_type_id; 49022944501Smrg 49122944501Smrg if ((r->count_props && !r->props) || 49222944501Smrg (r->count_props && !r->prop_values) || 49322944501Smrg (r->count_modes && !r->modes) || 49422944501Smrg (r->count_encoders && !r->encoders)) { 49522944501Smrg drmFree(r->props); 49622944501Smrg drmFree(r->prop_values); 49722944501Smrg drmFree(r->modes); 49822944501Smrg drmFree(r->encoders); 49922944501Smrg drmFree(r); 50022944501Smrg r = 0; 50122944501Smrg } 50222944501Smrg 50322944501Smrgerr_allocs: 50422944501Smrg drmFree(U642VOID(conn.prop_values_ptr)); 50522944501Smrg drmFree(U642VOID(conn.props_ptr)); 50622944501Smrg drmFree(U642VOID(conn.modes_ptr)); 50722944501Smrg drmFree(U642VOID(conn.encoders_ptr)); 50822944501Smrg 50922944501Smrg return r; 51022944501Smrg} 51122944501Smrg 51222944501Smrgint drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 51322944501Smrg{ 51422944501Smrg struct drm_mode_mode_cmd res; 51522944501Smrg 51622944501Smrg memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 51722944501Smrg res.connector_id = connector_id; 51822944501Smrg 519d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res); 52022944501Smrg} 52122944501Smrg 52222944501Smrgint drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info) 52322944501Smrg{ 52422944501Smrg struct drm_mode_mode_cmd res; 52522944501Smrg 52622944501Smrg memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo)); 52722944501Smrg res.connector_id = connector_id; 52822944501Smrg 529d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res); 53022944501Smrg} 53122944501Smrg 53222944501Smrg 53322944501SmrgdrmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) 53422944501Smrg{ 53522944501Smrg struct drm_mode_get_property prop; 53622944501Smrg drmModePropertyPtr r; 53722944501Smrg 53822944501Smrg prop.prop_id = property_id; 53922944501Smrg prop.count_enum_blobs = 0; 54022944501Smrg prop.count_values = 0; 54122944501Smrg prop.flags = 0; 54222944501Smrg prop.enum_blob_ptr = 0; 54322944501Smrg prop.values_ptr = 0; 54422944501Smrg 54522944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) 54622944501Smrg return 0; 54722944501Smrg 54822944501Smrg if (prop.count_values) 54922944501Smrg prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t))); 55022944501Smrg 55122944501Smrg if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM)) 55222944501Smrg prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum))); 55322944501Smrg 55422944501Smrg if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) { 55522944501Smrg prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 55622944501Smrg prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t))); 55722944501Smrg } 55822944501Smrg 55922944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) { 56022944501Smrg r = NULL; 56122944501Smrg goto err_allocs; 56222944501Smrg } 56322944501Smrg 56422944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 56522944501Smrg return NULL; 56622944501Smrg 56722944501Smrg r->prop_id = prop.prop_id; 56822944501Smrg r->count_values = prop.count_values; 56922944501Smrg 57022944501Smrg r->flags = prop.flags; 57122944501Smrg if (prop.count_values) 57222944501Smrg r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t)); 57322944501Smrg if (prop.flags & DRM_MODE_PROP_ENUM) { 57422944501Smrg r->count_enums = prop.count_enum_blobs; 57522944501Smrg r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); 57622944501Smrg } else if (prop.flags & DRM_MODE_PROP_BLOB) { 57722944501Smrg r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 57822944501Smrg r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t)); 57922944501Smrg r->count_blobs = prop.count_enum_blobs; 58022944501Smrg } 58122944501Smrg strncpy(r->name, prop.name, DRM_PROP_NAME_LEN); 58222944501Smrg r->name[DRM_PROP_NAME_LEN-1] = 0; 58322944501Smrg 58422944501Smrgerr_allocs: 58522944501Smrg drmFree(U642VOID(prop.values_ptr)); 58622944501Smrg drmFree(U642VOID(prop.enum_blob_ptr)); 58722944501Smrg 58822944501Smrg return r; 58922944501Smrg} 59022944501Smrg 59122944501Smrgvoid drmModeFreeProperty(drmModePropertyPtr ptr) 59222944501Smrg{ 59322944501Smrg if (!ptr) 59422944501Smrg return; 59522944501Smrg 59622944501Smrg drmFree(ptr->values); 59722944501Smrg drmFree(ptr->enums); 59822944501Smrg drmFree(ptr); 59922944501Smrg} 60022944501Smrg 60122944501SmrgdrmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id) 60222944501Smrg{ 60322944501Smrg struct drm_mode_get_blob blob; 60422944501Smrg drmModePropertyBlobPtr r; 60522944501Smrg 60622944501Smrg blob.length = 0; 60722944501Smrg blob.data = 0; 60822944501Smrg blob.blob_id = blob_id; 60922944501Smrg 61022944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) 61122944501Smrg return NULL; 61222944501Smrg 61322944501Smrg if (blob.length) 61422944501Smrg blob.data = VOID2U64(drmMalloc(blob.length)); 61522944501Smrg 61622944501Smrg if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) { 61722944501Smrg r = NULL; 61822944501Smrg goto err_allocs; 61922944501Smrg } 62022944501Smrg 62122944501Smrg if (!(r = drmMalloc(sizeof(*r)))) 622d049871aSmrg goto err_allocs; 62322944501Smrg 62422944501Smrg r->id = blob.blob_id; 62522944501Smrg r->length = blob.length; 62622944501Smrg r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length); 62722944501Smrg 62822944501Smrgerr_allocs: 62922944501Smrg drmFree(U642VOID(blob.data)); 63022944501Smrg return r; 63122944501Smrg} 63222944501Smrg 63322944501Smrgvoid drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) 63422944501Smrg{ 63522944501Smrg if (!ptr) 63622944501Smrg return; 63722944501Smrg 63822944501Smrg drmFree(ptr->data); 63922944501Smrg drmFree(ptr); 64022944501Smrg} 64122944501Smrg 64222944501Smrgint drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id, 64322944501Smrg uint64_t value) 64422944501Smrg{ 64522944501Smrg struct drm_mode_connector_set_property osp; 64622944501Smrg 64722944501Smrg osp.connector_id = connector_id; 64822944501Smrg osp.prop_id = property_id; 64922944501Smrg osp.value = value; 65022944501Smrg 651d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp); 65222944501Smrg} 65322944501Smrg 65422944501Smrg/* 65522944501Smrg * checks if a modesetting capable driver has attached to the pci id 65622944501Smrg * returns 0 if modesetting supported. 65722944501Smrg * -EINVAL or invalid bus id 65822944501Smrg * -ENOSYS if no modesetting support 65922944501Smrg*/ 66022944501Smrgint drmCheckModesettingSupported(const char *busid) 66122944501Smrg{ 66222944501Smrg#ifdef __linux__ 66322944501Smrg char pci_dev_dir[1024]; 66422944501Smrg int domain, bus, dev, func; 66522944501Smrg DIR *sysdir; 66622944501Smrg struct dirent *dent; 66722944501Smrg int found = 0, ret; 66822944501Smrg 66922944501Smrg ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func); 67022944501Smrg if (ret != 4) 67122944501Smrg return -EINVAL; 67222944501Smrg 67322944501Smrg sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm", 67422944501Smrg domain, bus, dev, func); 67522944501Smrg 67622944501Smrg sysdir = opendir(pci_dev_dir); 67722944501Smrg if (sysdir) { 67822944501Smrg dent = readdir(sysdir); 67922944501Smrg while (dent) { 68022944501Smrg if (!strncmp(dent->d_name, "controlD", 8)) { 68122944501Smrg found = 1; 68222944501Smrg break; 68322944501Smrg } 68422944501Smrg 68522944501Smrg dent = readdir(sysdir); 68622944501Smrg } 68722944501Smrg closedir(sysdir); 68822944501Smrg if (found) 68922944501Smrg return 0; 69022944501Smrg } 69122944501Smrg 69222944501Smrg sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/", 69322944501Smrg domain, bus, dev, func); 69422944501Smrg 69522944501Smrg sysdir = opendir(pci_dev_dir); 69622944501Smrg if (!sysdir) 69722944501Smrg return -EINVAL; 69822944501Smrg 69922944501Smrg dent = readdir(sysdir); 70022944501Smrg while (dent) { 70122944501Smrg if (!strncmp(dent->d_name, "drm:controlD", 12)) { 70222944501Smrg found = 1; 70322944501Smrg break; 70422944501Smrg } 70522944501Smrg 70622944501Smrg dent = readdir(sysdir); 70722944501Smrg } 70822944501Smrg 70922944501Smrg closedir(sysdir); 71022944501Smrg if (found) 71122944501Smrg return 0; 71222944501Smrg#endif 71322944501Smrg return -ENOSYS; 71422944501Smrg 71522944501Smrg} 71622944501Smrg 71722944501Smrgint drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size, 71822944501Smrg uint16_t *red, uint16_t *green, uint16_t *blue) 71922944501Smrg{ 72022944501Smrg struct drm_mode_crtc_lut l; 72122944501Smrg 72222944501Smrg l.crtc_id = crtc_id; 72322944501Smrg l.gamma_size = size; 72422944501Smrg l.red = VOID2U64(red); 72522944501Smrg l.green = VOID2U64(green); 72622944501Smrg l.blue = VOID2U64(blue); 72722944501Smrg 728d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l); 72922944501Smrg} 73022944501Smrg 73122944501Smrgint drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size, 73222944501Smrg uint16_t *red, uint16_t *green, uint16_t *blue) 73322944501Smrg{ 73422944501Smrg struct drm_mode_crtc_lut l; 73522944501Smrg 73622944501Smrg l.crtc_id = crtc_id; 73722944501Smrg l.gamma_size = size; 73822944501Smrg l.red = VOID2U64(red); 73922944501Smrg l.green = VOID2U64(green); 74022944501Smrg l.blue = VOID2U64(blue); 74122944501Smrg 742d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l); 74322944501Smrg} 74422944501Smrg 74522944501Smrgint drmHandleEvent(int fd, drmEventContextPtr evctx) 74622944501Smrg{ 74722944501Smrg char buffer[1024]; 74822944501Smrg int len, i; 74922944501Smrg struct drm_event *e; 75022944501Smrg struct drm_event_vblank *vblank; 75122944501Smrg 75222944501Smrg /* The DRM read semantics guarantees that we always get only 75322944501Smrg * complete events. */ 75422944501Smrg 75522944501Smrg len = read(fd, buffer, sizeof buffer); 75622944501Smrg if (len == 0) 75722944501Smrg return 0; 75822944501Smrg if (len < sizeof *e) 75922944501Smrg return -1; 76022944501Smrg 76122944501Smrg i = 0; 76222944501Smrg while (i < len) { 76322944501Smrg e = (struct drm_event *) &buffer[i]; 76422944501Smrg switch (e->type) { 76522944501Smrg case DRM_EVENT_VBLANK: 76622944501Smrg if (evctx->version < 1 || 76722944501Smrg evctx->vblank_handler == NULL) 76822944501Smrg break; 76922944501Smrg vblank = (struct drm_event_vblank *) e; 77022944501Smrg evctx->vblank_handler(fd, 77122944501Smrg vblank->sequence, 77222944501Smrg vblank->tv_sec, 77322944501Smrg vblank->tv_usec, 77422944501Smrg U642VOID (vblank->user_data)); 77522944501Smrg break; 77622944501Smrg case DRM_EVENT_FLIP_COMPLETE: 77722944501Smrg if (evctx->version < 2 || 77822944501Smrg evctx->page_flip_handler == NULL) 77922944501Smrg break; 78022944501Smrg vblank = (struct drm_event_vblank *) e; 78122944501Smrg evctx->page_flip_handler(fd, 78222944501Smrg vblank->sequence, 78322944501Smrg vblank->tv_sec, 78422944501Smrg vblank->tv_usec, 78522944501Smrg U642VOID (vblank->user_data)); 78622944501Smrg break; 78722944501Smrg default: 78822944501Smrg break; 78922944501Smrg } 79022944501Smrg i += e->length; 79122944501Smrg } 79222944501Smrg 79322944501Smrg return 0; 79422944501Smrg} 79522944501Smrg 79622944501Smrgint drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id, 79722944501Smrg uint32_t flags, void *user_data) 79822944501Smrg{ 79922944501Smrg struct drm_mode_crtc_page_flip flip; 80022944501Smrg 80122944501Smrg flip.fb_id = fb_id; 80222944501Smrg flip.crtc_id = crtc_id; 80322944501Smrg flip.user_data = VOID2U64(user_data); 80422944501Smrg flip.flags = flags; 80522944501Smrg flip.reserved = 0; 80622944501Smrg 807d049871aSmrg return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip); 80822944501Smrg} 809