2 * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * Copyright (c) 2007-2008 Dave Airlie <airlied@linux.ie>
4 * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 #include "arosdrmmode.h"
31 #define U642VOID(x) ((void *)(unsigned long)(x))
32 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
34 static inline int DRM_IOCTL(int fd
, int cmd
, void *arg
)
36 int ret
= drmIoctl(fd
, cmd
, arg
);
37 return ret
< 0 ? -errno
: ret
;
44 void* drmAllocCpy(void *array
, int count
, int entry_size
)
49 if (!count
|| !array
|| !entry_size
)
52 if (!(r
= drmMalloc(count
*entry_size
)))
55 for (i
= 0; i
< count
; i
++)
56 memcpy(r
+(entry_size
*i
), array
+(entry_size
*i
), entry_size
);
62 * A couple of free functions.
65 void drmModeFreeModeInfo(drmModeModeInfoPtr ptr
)
73 void drmModeFreeResources(drmModeResPtr ptr
)
82 void drmModeFreeCrtc(drmModeCrtcPtr ptr
)
91 void drmModeFreeConnector(drmModeConnectorPtr ptr
)
96 drmFree(ptr
->encoders
);
97 drmFree(ptr
->prop_values
);
104 void drmModeFreeEncoder(drmModeEncoderPtr ptr
)
110 * ModeSetting functions.
113 drmModeResPtr
drmModeGetResources(int fd
)
115 struct drm_mode_card_res res
, counts
;
119 memset(&res
, 0, sizeof(struct drm_mode_card_res
));
120 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETRESOURCES
, &res
))
126 res
.fb_id_ptr
= VOID2U64(drmMalloc(res
.count_fbs
*sizeof(uint32_t)));
130 if (res
.count_crtcs
) {
131 res
.crtc_id_ptr
= VOID2U64(drmMalloc(res
.count_crtcs
*sizeof(uint32_t)));
132 if (!res
.crtc_id_ptr
)
135 if (res
.count_connectors
) {
136 res
.connector_id_ptr
= VOID2U64(drmMalloc(res
.count_connectors
*sizeof(uint32_t)));
137 if (!res
.connector_id_ptr
)
140 if (res
.count_encoders
) {
141 res
.encoder_id_ptr
= VOID2U64(drmMalloc(res
.count_encoders
*sizeof(uint32_t)));
142 if (!res
.encoder_id_ptr
)
146 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETRESOURCES
, &res
))
149 /* The number of available connectors and etc may have changed with a
150 * hotplug event in between the ioctls, in which case the field is
151 * silently ignored by the kernel.
153 if (counts
.count_fbs
< res
.count_fbs
||
154 counts
.count_crtcs
< res
.count_crtcs
||
155 counts
.count_connectors
< res
.count_connectors
||
156 counts
.count_encoders
< res
.count_encoders
)
158 drmFree(U642VOID(res
.fb_id_ptr
));
159 drmFree(U642VOID(res
.crtc_id_ptr
));
160 drmFree(U642VOID(res
.connector_id_ptr
));
161 drmFree(U642VOID(res
.encoder_id_ptr
));
169 if (!(r
= drmMalloc(sizeof(*r
))))
172 r
->min_width
= res
.min_width
;
173 r
->max_width
= res
.max_width
;
174 r
->min_height
= res
.min_height
;
175 r
->max_height
= res
.max_height
;
176 r
->count_fbs
= res
.count_fbs
;
177 r
->count_crtcs
= res
.count_crtcs
;
178 r
->count_connectors
= res
.count_connectors
;
179 r
->count_encoders
= res
.count_encoders
;
181 r
->fbs
= drmAllocCpy(U642VOID(res
.fb_id_ptr
), res
.count_fbs
, sizeof(uint32_t));
182 r
->crtcs
= drmAllocCpy(U642VOID(res
.crtc_id_ptr
), res
.count_crtcs
, sizeof(uint32_t));
183 r
->connectors
= drmAllocCpy(U642VOID(res
.connector_id_ptr
), res
.count_connectors
, sizeof(uint32_t));
184 r
->encoders
= drmAllocCpy(U642VOID(res
.encoder_id_ptr
), res
.count_encoders
, sizeof(uint32_t));
185 if ((res
.count_fbs
&& !r
->fbs
) ||
186 (res
.count_crtcs
&& !r
->crtcs
) ||
187 (res
.count_connectors
&& !r
->connectors
) ||
188 (res
.count_encoders
&& !r
->encoders
))
192 drmFree(r
->connectors
);
193 drmFree(r
->encoders
);
199 drmFree(U642VOID(res
.fb_id_ptr
));
200 drmFree(U642VOID(res
.crtc_id_ptr
));
201 drmFree(U642VOID(res
.connector_id_ptr
));
202 drmFree(U642VOID(res
.encoder_id_ptr
));
207 int drmModeAddFB(int fd
, uint32_t width
, uint32_t height
, uint8_t depth
,
208 uint8_t bpp
, uint32_t pitch
, uint32_t bo_handle
,
211 struct drm_mode_fb_cmd f
;
219 f
.handle
= bo_handle
;
221 if ((ret
= DRM_IOCTL(fd
, DRM_IOCTL_MODE_ADDFB
, &f
)))
228 int drmModeRmFB(int fd
, uint32_t bufferId
)
230 return DRM_IOCTL(fd
, DRM_IOCTL_MODE_RMFB
, &bufferId
);
239 drmModeCrtcPtr
drmModeGetCrtc(int fd
, uint32_t crtcId
)
241 struct drm_mode_crtc crtc
;
244 crtc
.crtc_id
= crtcId
;
246 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETCRTC
, &crtc
))
253 if (!(r
= drmMalloc(sizeof(*r
))))
256 r
->crtc_id
= crtc
.crtc_id
;
259 r
->mode_valid
= crtc
.mode_valid
;
261 memcpy(&r
->mode
, &crtc
.mode
, sizeof(struct drm_mode_modeinfo
));
262 r
->buffer_id
= crtc
.fb_id
;
263 r
->gamma_size
= crtc
.gamma_size
;
268 int drmModeSetCrtc(int fd
, uint32_t crtcId
, uint32_t bufferId
,
269 uint32_t x
, uint32_t y
, uint32_t *connectors
, int count
,
270 drmModeModeInfoPtr mode
)
272 struct drm_mode_crtc crtc
;
276 crtc
.crtc_id
= crtcId
;
277 crtc
.fb_id
= bufferId
;
278 crtc
.set_connectors_ptr
= VOID2U64(connectors
);
279 crtc
.count_connectors
= count
;
281 memcpy(&crtc
.mode
, mode
, sizeof(struct drm_mode_modeinfo
));
286 return DRM_IOCTL(fd
, DRM_IOCTL_MODE_SETCRTC
, &crtc
);
290 * Cursor manipulation
293 int drmModeSetCursor(int fd
, uint32_t crtcId
, uint32_t bo_handle
, uint32_t width
, uint32_t height
)
295 struct drm_mode_cursor arg
;
297 arg
.flags
= DRM_MODE_CURSOR_BO
;
298 arg
.crtc_id
= crtcId
;
301 arg
.handle
= bo_handle
;
303 return DRM_IOCTL(fd
, DRM_IOCTL_MODE_CURSOR
, &arg
);
306 int drmModeMoveCursor(int fd
, uint32_t crtcId
, int x
, int y
)
308 struct drm_mode_cursor arg
;
310 arg
.flags
= DRM_MODE_CURSOR_MOVE
;
311 arg
.crtc_id
= crtcId
;
315 return DRM_IOCTL(fd
, DRM_IOCTL_MODE_CURSOR
, &arg
);
321 drmModeEncoderPtr
drmModeGetEncoder(int fd
, uint32_t encoder_id
)
323 struct drm_mode_get_encoder enc
;
324 drmModeEncoderPtr r
= NULL
;
326 enc
.encoder_id
= encoder_id
;
327 enc
.encoder_type
= 0;
328 enc
.possible_crtcs
= 0;
329 enc
.possible_clones
= 0;
331 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETENCODER
, &enc
))
334 if (!(r
= drmMalloc(sizeof(*r
))))
337 r
->encoder_id
= enc
.encoder_id
;
338 r
->crtc_id
= enc
.crtc_id
;
339 r
->encoder_type
= enc
.encoder_type
;
340 r
->possible_crtcs
= enc
.possible_crtcs
;
341 r
->possible_clones
= enc
.possible_clones
;
347 * Connector manipulation
350 drmModeConnectorPtr
drmModeGetConnector(int fd
, uint32_t connector_id
)
352 struct drm_mode_get_connector conn
, counts
;
353 drmModeConnectorPtr r
= NULL
;
356 memset(&conn
, 0, sizeof(struct drm_mode_get_connector
));
357 conn
.connector_id
= connector_id
;
359 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETCONNECTOR
, &conn
))
364 if (conn
.count_props
) {
365 conn
.props_ptr
= VOID2U64(drmMalloc(conn
.count_props
*sizeof(uint32_t)));
368 conn
.prop_values_ptr
= VOID2U64(drmMalloc(conn
.count_props
*sizeof(uint64_t)));
369 if (!conn
.prop_values_ptr
)
373 if (conn
.count_modes
) {
374 conn
.modes_ptr
= VOID2U64(drmMalloc(conn
.count_modes
*sizeof(struct drm_mode_modeinfo
)));
379 if (conn
.count_encoders
) {
380 conn
.encoders_ptr
= VOID2U64(drmMalloc(conn
.count_encoders
*sizeof(uint32_t)));
381 if (!conn
.encoders_ptr
)
385 if (drmIoctl(fd
, DRM_IOCTL_MODE_GETCONNECTOR
, &conn
))
388 /* The number of available connectors and etc may have changed with a
389 * hotplug event in between the ioctls, in which case the field is
390 * silently ignored by the kernel.
392 if (counts
.count_props
< conn
.count_props
||
393 counts
.count_modes
< conn
.count_modes
||
394 counts
.count_encoders
< conn
.count_encoders
) {
395 drmFree(U642VOID(conn
.props_ptr
));
396 drmFree(U642VOID(conn
.prop_values_ptr
));
397 drmFree(U642VOID(conn
.modes_ptr
));
398 drmFree(U642VOID(conn
.encoders_ptr
));
403 if(!(r
= drmMalloc(sizeof(*r
)))) {
407 r
->connector_id
= conn
.connector_id
;
408 r
->encoder_id
= conn
.encoder_id
;
409 r
->connection
= conn
.connection
;
410 r
->mmWidth
= conn
.mm_width
;
411 r
->mmHeight
= conn
.mm_height
;
412 /* convert subpixel from kernel to userspace */
413 r
->subpixel
= conn
.subpixel
+ 1;
414 r
->count_modes
= conn
.count_modes
;
415 r
->count_props
= conn
.count_props
;
416 r
->props
= drmAllocCpy(U642VOID(conn
.props_ptr
), conn
.count_props
, sizeof(uint32_t));
417 r
->prop_values
= drmAllocCpy(U642VOID(conn
.prop_values_ptr
), conn
.count_props
, sizeof(uint64_t));
418 r
->modes
= drmAllocCpy(U642VOID(conn
.modes_ptr
), conn
.count_modes
, sizeof(struct drm_mode_modeinfo
));
419 r
->count_encoders
= conn
.count_encoders
;
420 r
->encoders
= drmAllocCpy(U642VOID(conn
.encoders_ptr
), conn
.count_encoders
, sizeof(uint32_t));
421 r
->connector_type
= conn
.connector_type
;
422 r
->connector_type_id
= conn
.connector_type_id
;
424 if ((r
->count_props
&& !r
->props
) ||
425 (r
->count_props
&& !r
->prop_values
) ||
426 (r
->count_modes
&& !r
->modes
) ||
427 (r
->count_encoders
&& !r
->encoders
)) {
429 drmFree(r
->prop_values
);
431 drmFree(r
->encoders
);
437 drmFree(U642VOID(conn
.prop_values_ptr
));
438 drmFree(U642VOID(conn
.props_ptr
));
439 drmFree(U642VOID(conn
.modes_ptr
));
440 drmFree(U642VOID(conn
.encoders_ptr
));
445 int drmModeAttachMode(int fd
, uint32_t connector_id
, drmModeModeInfoPtr mode_info
)
447 struct drm_mode_mode_cmd res
;
449 memcpy(&res
.mode
, mode_info
, sizeof(struct drm_mode_modeinfo
));
450 res
.connector_id
= connector_id
;
452 return DRM_IOCTL(fd
, DRM_IOCTL_MODE_ATTACHMODE
, &res
);
455 int drmModeDetachMode(int fd
, uint32_t connector_id
, drmModeModeInfoPtr mode_info
)
457 struct drm_mode_mode_cmd res
;
459 memcpy(&res
.mode
, mode_info
, sizeof(struct drm_mode_modeinfo
));
460 res
.connector_id
= connector_id
;
462 return DRM_IOCTL(fd
, DRM_IOCTL_MODE_DETACHMODE
, &res
);