3 * Header for DRM modesetting interface.
5 * \author Jakob Bornecrantz <wallbraker@gmail.com>
7 * \par Acknowledgements:
8 * Feb 2007, Dave Airlie <airlied@linux.ie>
12 * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
13 * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie>
14 * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com>
16 * Permission is hereby granted, free of charge, to any person obtaining a
17 * copy of this software and associated documentation files (the "Software"),
18 * to deal in the Software without restriction, including without limitation
19 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 * and/or sell copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following conditions:
23 * The above copyright notice and this permission notice shall be included in
24 * all copies or substantial portions of the Software.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
37 * TODO the types we are after are defined in diffrent headers on diffrent
38 * platforms find which headers to include to get uint32_t
41 #include <sys/ioctl.h>
44 #include "xf86drmMode.h"
51 #define U642VOID(x) ((void *)(unsigned long)(x))
52 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
58 void* drmAllocCpy(void *array
, int count
, int entry_size
)
63 if (!count
|| !array
|| !entry_size
)
66 if (!(r
= drmMalloc(count
*entry_size
)))
69 for (i
= 0; i
< count
; i
++)
70 memcpy(r
+(entry_size
*i
), array
+(entry_size
*i
), entry_size
);
76 * A couple of free functions.
79 void drmModeFreeModeInfo(drmModeModeInfoPtr ptr
)
87 void drmModeFreeResources(drmModeResPtr ptr
)
96 void drmModeFreeFB(drmModeFBPtr ptr
)
101 /* we might add more frees later. */
105 void drmModeFreeCrtc(drmModeCrtcPtr ptr
)
114 void drmModeFreeConnector(drmModeConnectorPtr ptr
)
124 void drmModeFreeEncoder(drmModeEncoderPtr ptr
)
130 * ModeSetting functions.
133 drmModeResPtr
drmModeGetResources(int fd
)
135 struct drm_mode_card_res res
;
138 memset(&res
, 0, sizeof(struct drm_mode_card_res
));
140 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETRESOURCES
, &res
))
144 res
.fb_id_ptr
= VOID2U64(drmMalloc(res
.count_fbs
*sizeof(uint32_t)));
146 res
.crtc_id_ptr
= VOID2U64(drmMalloc(res
.count_crtcs
*sizeof(uint32_t)));
147 if (res
.count_connectors
)
148 res
.connector_id_ptr
= VOID2U64(drmMalloc(res
.count_connectors
*sizeof(uint32_t)));
149 if (res
.count_encoders
)
150 res
.encoder_id_ptr
= VOID2U64(drmMalloc(res
.count_encoders
*sizeof(uint32_t)));
152 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETRESOURCES
, &res
)) {
162 if (!(r
= drmMalloc(sizeof(*r
))))
165 r
->min_width
= res
.min_width
;
166 r
->max_width
= res
.max_width
;
167 r
->min_height
= res
.min_height
;
168 r
->max_height
= res
.max_height
;
169 r
->count_fbs
= res
.count_fbs
;
170 r
->count_crtcs
= res
.count_crtcs
;
171 r
->count_connectors
= res
.count_connectors
;
172 r
->count_encoders
= res
.count_encoders
;
173 /* TODO we realy should test if these allocs fails. */
174 r
->fbs
= drmAllocCpy(U642VOID(res
.fb_id_ptr
), res
.count_fbs
, sizeof(uint32_t));
175 r
->crtcs
= drmAllocCpy(U642VOID(res
.crtc_id_ptr
), res
.count_crtcs
, sizeof(uint32_t));
176 r
->connectors
= drmAllocCpy(U642VOID(res
.connector_id_ptr
), res
.count_connectors
, sizeof(uint32_t));
177 r
->encoders
= drmAllocCpy(U642VOID(res
.encoder_id_ptr
), res
.count_encoders
, sizeof(uint32_t));
180 drmFree(U642VOID(res
.fb_id_ptr
));
181 drmFree(U642VOID(res
.crtc_id_ptr
));
182 drmFree(U642VOID(res
.connector_id_ptr
));
183 drmFree(U642VOID(res
.encoder_id_ptr
));
188 int drmModeAddFB(int fd
, uint32_t width
, uint32_t height
, uint8_t depth
,
189 uint8_t bpp
, uint32_t pitch
, uint32_t bo_handle
,
192 struct drm_mode_fb_cmd f
;
200 f
.handle
= bo_handle
;
202 if ((ret
= drmIoctl(fd
, DRM_IOCTL_MODE_ADDFB
, &f
)))
209 int drmModeRmFB(int fd
, uint32_t bufferId
)
211 return drmIoctl(fd
, DRM_IOCTL_MODE_RMFB
, &bufferId
);
216 drmModeFBPtr
drmModeGetFB(int fd
, uint32_t buf
)
218 struct drm_mode_fb_cmd info
;
223 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETFB
, &info
))
226 if (!(r
= drmMalloc(sizeof(*r
))))
229 r
->fb_id
= info
.fb_id
;
230 r
->width
= info
.width
;
231 r
->height
= info
.height
;
232 r
->pitch
= info
.pitch
;
234 r
->handle
= info
.handle
;
235 r
->depth
= info
.depth
;
245 drmModeCrtcPtr
drmModeGetCrtc(int fd
, uint32_t crtcId
)
247 struct drm_mode_crtc crtc
;
250 crtc
.crtc_id
= crtcId
;
252 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETCRTC
, &crtc
))
259 if (!(r
= drmMalloc(sizeof(*r
))))
262 r
->crtc_id
= crtc
.crtc_id
;
265 r
->mode_valid
= crtc
.mode_valid
;
267 memcpy(&r
->mode
, &crtc
.mode
, sizeof(struct drm_mode_modeinfo
));
268 r
->buffer_id
= crtc
.fb_id
;
269 r
->gamma_size
= crtc
.gamma_size
;
274 int drmModeSetCrtc(int fd
, uint32_t crtcId
, uint32_t bufferId
,
275 uint32_t x
, uint32_t y
, uint32_t *connectors
, int count
,
276 drmModeModeInfoPtr mode
)
278 struct drm_mode_crtc crtc
;
282 crtc
.crtc_id
= crtcId
;
283 crtc
.fb_id
= bufferId
;
284 crtc
.set_connectors_ptr
= VOID2U64(connectors
);
285 crtc
.count_connectors
= count
;
287 memcpy(&crtc
.mode
, mode
, sizeof(struct drm_mode_modeinfo
));
292 return drmIoctl(fd
, DRM_IOCTL_MODE_SETCRTC
, &crtc
);
296 * Cursor manipulation
299 int drmModeSetCursor(int fd
, uint32_t crtcId
, uint32_t bo_handle
, uint32_t width
, uint32_t height
)
301 struct drm_mode_cursor arg
;
303 arg
.flags
= DRM_MODE_CURSOR_BO
;
304 arg
.crtc_id
= crtcId
;
307 arg
.handle
= bo_handle
;
309 return drmIoctl(fd
, DRM_IOCTL_MODE_CURSOR
, &arg
);
312 int drmModeMoveCursor(int fd
, uint32_t crtcId
, int x
, int y
)
314 struct drm_mode_cursor arg
;
316 arg
.flags
= DRM_MODE_CURSOR_MOVE
;
317 arg
.crtc_id
= crtcId
;
321 return drmIoctl(fd
, DRM_IOCTL_MODE_CURSOR
, &arg
);
327 drmModeEncoderPtr
drmModeGetEncoder(int fd
, uint32_t encoder_id
)
329 struct drm_mode_get_encoder enc
;
330 drmModeEncoderPtr r
= NULL
;
332 enc
.encoder_id
= encoder_id
;
333 enc
.encoder_type
= 0;
334 enc
.possible_crtcs
= 0;
335 enc
.possible_clones
= 0;
337 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETENCODER
, &enc
))
340 if (!(r
= drmMalloc(sizeof(*r
))))
343 r
->encoder_id
= enc
.encoder_id
;
344 r
->crtc_id
= enc
.crtc_id
;
345 r
->encoder_type
= enc
.encoder_type
;
346 r
->possible_crtcs
= enc
.possible_crtcs
;
347 r
->possible_clones
= enc
.possible_clones
;
353 * Connector manipulation
356 drmModeConnectorPtr
drmModeGetConnector(int fd
, uint32_t connector_id
)
358 struct drm_mode_get_connector conn
;
359 drmModeConnectorPtr r
= NULL
;
361 conn
.connector_id
= connector_id
;
362 conn
.connector_type_id
= 0;
363 conn
.connector_type
= 0;
364 conn
.count_modes
= 0;
366 conn
.count_props
= 0;
368 conn
.prop_values_ptr
= 0;
369 conn
.count_encoders
= 0;
370 conn
.encoders_ptr
= 0;
372 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETCONNECTOR
, &conn
))
375 if (conn
.count_props
) {
376 conn
.props_ptr
= VOID2U64(drmMalloc(conn
.count_props
*sizeof(uint32_t)));
377 conn
.prop_values_ptr
= VOID2U64(drmMalloc(conn
.count_props
*sizeof(uint64_t)));
380 if (conn
.count_modes
)
381 conn
.modes_ptr
= VOID2U64(drmMalloc(conn
.count_modes
*sizeof(struct drm_mode_modeinfo
)));
383 if (conn
.count_encoders
)
384 conn
.encoders_ptr
= VOID2U64(drmMalloc(conn
.count_encoders
*sizeof(uint32_t)));
386 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETCONNECTOR
, &conn
))
389 if(!(r
= drmMalloc(sizeof(*r
)))) {
393 r
->connector_id
= conn
.connector_id
;
394 r
->encoder_id
= conn
.encoder_id
;
395 r
->connection
= conn
.connection
;
396 r
->mmWidth
= conn
.mm_width
;
397 r
->mmHeight
= conn
.mm_height
;
398 /* convert subpixel from kernel to userspace */
399 r
->subpixel
= conn
.subpixel
+ 1;
400 r
->count_modes
= conn
.count_modes
;
401 /* TODO we should test if these alloc & cpy fails. */
402 r
->count_props
= conn
.count_props
;
403 r
->props
= drmAllocCpy(U642VOID(conn
.props_ptr
), conn
.count_props
, sizeof(uint32_t));
404 r
->prop_values
= drmAllocCpy(U642VOID(conn
.prop_values_ptr
), conn
.count_props
, sizeof(uint64_t));
405 r
->modes
= drmAllocCpy(U642VOID(conn
.modes_ptr
), conn
.count_modes
, sizeof(struct drm_mode_modeinfo
));
406 r
->count_encoders
= conn
.count_encoders
;
407 r
->encoders
= drmAllocCpy(U642VOID(conn
.encoders_ptr
), conn
.count_encoders
, sizeof(uint32_t));
408 r
->connector_type
= conn
.connector_type
;
409 r
->connector_type_id
= conn
.connector_type_id
;
411 if (!r
->props
|| !r
->prop_values
|| !r
->modes
|| !r
->encoders
)
415 drmFree(U642VOID(conn
.prop_values_ptr
));
416 drmFree(U642VOID(conn
.props_ptr
));
417 drmFree(U642VOID(conn
.modes_ptr
));
418 drmFree(U642VOID(conn
.encoders_ptr
));
423 int drmModeAttachMode(int fd
, uint32_t connector_id
, drmModeModeInfoPtr mode_info
)
425 struct drm_mode_mode_cmd res
;
427 memcpy(&res
.mode
, mode_info
, sizeof(struct drm_mode_modeinfo
));
428 res
.connector_id
= connector_id
;
430 return drmIoctl(fd
, DRM_IOCTL_MODE_ATTACHMODE
, &res
);
433 int drmModeDetachMode(int fd
, uint32_t connector_id
, drmModeModeInfoPtr mode_info
)
435 struct drm_mode_mode_cmd res
;
437 memcpy(&res
.mode
, mode_info
, sizeof(struct drm_mode_modeinfo
));
438 res
.connector_id
= connector_id
;
440 return drmIoctl(fd
, DRM_IOCTL_MODE_DETACHMODE
, &res
);
444 drmModePropertyPtr
drmModeGetProperty(int fd
, uint32_t property_id
)
446 struct drm_mode_get_property prop
;
447 drmModePropertyPtr r
;
449 prop
.prop_id
= property_id
;
450 prop
.count_enum_blobs
= 0;
451 prop
.count_values
= 0;
453 prop
.enum_blob_ptr
= 0;
456 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETPROPERTY
, &prop
))
459 if (prop
.count_values
)
460 prop
.values_ptr
= VOID2U64(drmMalloc(prop
.count_values
* sizeof(uint64_t)));
462 if (prop
.count_enum_blobs
&& (prop
.flags
& DRM_MODE_PROP_ENUM
))
463 prop
.enum_blob_ptr
= VOID2U64(drmMalloc(prop
.count_enum_blobs
* sizeof(struct drm_mode_property_enum
)));
465 if (prop
.count_enum_blobs
&& (prop
.flags
& DRM_MODE_PROP_BLOB
)) {
466 prop
.values_ptr
= VOID2U64(drmMalloc(prop
.count_enum_blobs
* sizeof(uint32_t)));
467 prop
.enum_blob_ptr
= VOID2U64(drmMalloc(prop
.count_enum_blobs
* sizeof(uint32_t)));
470 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETPROPERTY
, &prop
)) {
475 if (!(r
= drmMalloc(sizeof(*r
))))
478 r
->prop_id
= prop
.prop_id
;
479 r
->count_values
= prop
.count_values
;
481 r
->flags
= prop
.flags
;
482 if (prop
.count_values
)
483 r
->values
= drmAllocCpy(U642VOID(prop
.values_ptr
), prop
.count_values
, sizeof(uint64_t));
484 if (prop
.flags
& DRM_MODE_PROP_ENUM
) {
485 r
->count_enums
= prop
.count_enum_blobs
;
486 r
->enums
= drmAllocCpy(U642VOID(prop
.enum_blob_ptr
), prop
.count_enum_blobs
, sizeof(struct drm_mode_property_enum
));
487 } else if (prop
.flags
& DRM_MODE_PROP_BLOB
) {
488 r
->values
= drmAllocCpy(U642VOID(prop
.values_ptr
), prop
.count_enum_blobs
, sizeof(uint32_t));
489 r
->blob_ids
= drmAllocCpy(U642VOID(prop
.enum_blob_ptr
), prop
.count_enum_blobs
, sizeof(uint32_t));
490 r
->count_blobs
= prop
.count_enum_blobs
;
492 strncpy(r
->name
, prop
.name
, DRM_PROP_NAME_LEN
);
493 r
->name
[DRM_PROP_NAME_LEN
-1] = 0;
496 drmFree(U642VOID(prop
.values_ptr
));
497 drmFree(U642VOID(prop
.enum_blob_ptr
));
502 void drmModeFreeProperty(drmModePropertyPtr ptr
)
507 drmFree(ptr
->values
);
512 drmModePropertyBlobPtr
drmModeGetPropertyBlob(int fd
, uint32_t blob_id
)
514 struct drm_mode_get_blob blob
;
515 drmModePropertyBlobPtr r
;
519 blob
.blob_id
= blob_id
;
521 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETPROPBLOB
, &blob
))
525 blob
.data
= VOID2U64(drmMalloc(blob
.length
));
527 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETPROPBLOB
, &blob
)) {
532 if (!(r
= drmMalloc(sizeof(*r
))))
535 r
->id
= blob
.blob_id
;
536 r
->length
= blob
.length
;
537 r
->data
= drmAllocCpy(U642VOID(blob
.data
), 1, blob
.length
);
540 drmFree(U642VOID(blob
.data
));
544 void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr
)
553 int drmModeConnectorSetProperty(int fd
, uint32_t connector_id
, uint32_t property_id
,
556 struct drm_mode_connector_set_property osp
;
559 osp
.connector_id
= connector_id
;
560 osp
.prop_id
= property_id
;
563 if ((ret
= drmIoctl(fd
, DRM_IOCTL_MODE_SETPROPERTY
, &osp
)))
570 * checks if a modesetting capable driver has attached to the pci id
571 * returns 0 if modesetting supported.
572 * -EINVAL or invalid bus id
573 * -ENOSYS if no modesetting support
575 int drmCheckModesettingSupported(const char *busid
)
578 char pci_dev_dir
[1024];
579 int domain
, bus
, dev
, func
;
584 ret
= sscanf(busid
, "pci:%04x:%02x:%02x.%d", &domain
, &bus
, &dev
, &func
);
588 sprintf(pci_dev_dir
, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
589 domain
, bus
, dev
, func
);
591 sysdir
= opendir(pci_dev_dir
);
593 dent
= readdir(sysdir
);
595 if (!strncmp(dent
->d_name
, "controlD", 8)) {
600 dent
= readdir(sysdir
);
607 sprintf(pci_dev_dir
, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
608 domain
, bus
, dev
, func
);
610 sysdir
= opendir(pci_dev_dir
);
614 dent
= readdir(sysdir
);
616 if (!strncmp(dent
->d_name
, "drm:controlD", 12)) {
621 dent
= readdir(sysdir
);
632 int drmModeCrtcGetGamma(int fd
, uint32_t crtc_id
, uint32_t size
,
633 uint16_t *red
, uint16_t *green
, uint16_t *blue
)
636 struct drm_mode_crtc_lut l
;
640 l
.red
= VOID2U64(red
);
641 l
.green
= VOID2U64(green
);
642 l
.blue
= VOID2U64(blue
);
644 if ((ret
= drmIoctl(fd
, DRM_IOCTL_MODE_GETGAMMA
, &l
)))
650 int drmModeCrtcSetGamma(int fd
, uint32_t crtc_id
, uint32_t size
,
651 uint16_t *red
, uint16_t *green
, uint16_t *blue
)
654 struct drm_mode_crtc_lut l
;
658 l
.red
= VOID2U64(red
);
659 l
.green
= VOID2U64(green
);
660 l
.blue
= VOID2U64(blue
);
662 if ((ret
= drmIoctl(fd
, DRM_IOCTL_MODE_SETGAMMA
, &l
)))