• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * \file xf86drmMode.c
3  * Header for DRM modesetting interface.
4  *
5  * \author Jakob Bornecrantz <wallbraker@gmail.com>
6  *
7  * \par Acknowledgements:
8  * Feb 2007, Dave Airlie <airlied@linux.ie>
9  */
10 
11 /*
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>
15  *
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:
22  *
23  * The above copyright notice and this permission notice shall be included in
24  * all copies or substantial portions of the Software.
25  *
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
32  * IN THE SOFTWARE.
33  *
34  */
35 
36 /*
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
39  */
40 #include <stdint.h>
41 #include <sys/ioctl.h>
42 #include <stdio.h>
43 
44 #include "xf86drmMode.h"
45 #include "xf86drm.h"
46 #include <drm.h>
47 #include <string.h>
48 #include <dirent.h>
49 #include <errno.h>
50 
51 #define U642VOID(x) ((void *)(unsigned long)(x))
52 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
53 
54 /*
55  * Util functions
56  */
57 
drmAllocCpy(void * array,int count,int entry_size)58 void* drmAllocCpy(void *array, int count, int entry_size)
59 {
60 	char *r;
61 	int i;
62 
63 	if (!count || !array || !entry_size)
64 		return 0;
65 
66 	if (!(r = drmMalloc(count*entry_size)))
67 		return 0;
68 
69 	for (i = 0; i < count; i++)
70 		memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
71 
72 	return r;
73 }
74 
75 /*
76  * A couple of free functions.
77  */
78 
drmModeFreeModeInfo(drmModeModeInfoPtr ptr)79 void drmModeFreeModeInfo(drmModeModeInfoPtr ptr)
80 {
81 	if (!ptr)
82 		return;
83 
84 	drmFree(ptr);
85 }
86 
drmModeFreeResources(drmModeResPtr ptr)87 void drmModeFreeResources(drmModeResPtr ptr)
88 {
89 	if (!ptr)
90 		return;
91 
92 	drmFree(ptr);
93 
94 }
95 
drmModeFreeFB(drmModeFBPtr ptr)96 void drmModeFreeFB(drmModeFBPtr ptr)
97 {
98 	if (!ptr)
99 		return;
100 
101 	/* we might add more frees later. */
102 	drmFree(ptr);
103 }
104 
drmModeFreeCrtc(drmModeCrtcPtr ptr)105 void drmModeFreeCrtc(drmModeCrtcPtr ptr)
106 {
107 	if (!ptr)
108 		return;
109 
110 	drmFree(ptr);
111 
112 }
113 
drmModeFreeConnector(drmModeConnectorPtr ptr)114 void drmModeFreeConnector(drmModeConnectorPtr ptr)
115 {
116 	if (!ptr)
117 		return;
118 
119 	drmFree(ptr->encoders);
120 	drmFree(ptr->prop_values);
121 	drmFree(ptr->props);
122 	drmFree(ptr->modes);
123 	drmFree(ptr);
124 
125 }
126 
drmModeFreeEncoder(drmModeEncoderPtr ptr)127 void drmModeFreeEncoder(drmModeEncoderPtr ptr)
128 {
129 	drmFree(ptr);
130 }
131 
132 /*
133  * ModeSetting functions.
134  */
135 
drmModeGetResources(int fd)136 drmModeResPtr drmModeGetResources(int fd)
137 {
138 	struct drm_mode_card_res res;
139 	drmModeResPtr r = 0;
140 
141 	memset(&res, 0, sizeof(struct drm_mode_card_res));
142 
143 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
144 		return 0;
145 
146 	if (res.count_fbs)
147 		res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
148 	if (res.count_crtcs)
149 		res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
150 	if (res.count_connectors)
151 		res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
152 	if (res.count_encoders)
153 		res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
154 
155 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
156 		r = NULL;
157 		goto err_allocs;
158 	}
159 
160 	/*
161 	 * return
162 	 */
163 
164 
165 	if (!(r = drmMalloc(sizeof(*r))))
166 		return 0;
167 
168 	r->min_width     = res.min_width;
169 	r->max_width     = res.max_width;
170 	r->min_height    = res.min_height;
171 	r->max_height    = res.max_height;
172 	r->count_fbs     = res.count_fbs;
173 	r->count_crtcs   = res.count_crtcs;
174 	r->count_connectors = res.count_connectors;
175 	r->count_encoders = res.count_encoders;
176 	/* TODO we realy should test if these allocs fails. */
177 	r->fbs           = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
178 	r->crtcs         = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
179 	r->connectors       = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
180 	r->encoders      = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
181 
182 err_allocs:
183 	drmFree(U642VOID(res.fb_id_ptr));
184 	drmFree(U642VOID(res.crtc_id_ptr));
185 	drmFree(U642VOID(res.connector_id_ptr));
186 	drmFree(U642VOID(res.encoder_id_ptr));
187 
188 	return r;
189 }
190 
drmModeAddFB(int fd,uint32_t width,uint32_t height,uint8_t depth,uint8_t bpp,uint32_t pitch,uint32_t bo_handle,uint32_t * buf_id)191 int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
192                  uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
193 		 uint32_t *buf_id)
194 {
195 	struct drm_mode_fb_cmd f;
196 	int ret;
197 
198 	f.width  = width;
199 	f.height = height;
200 	f.pitch  = pitch;
201 	f.bpp    = bpp;
202 	f.depth  = depth;
203 	f.handle = bo_handle;
204 
205 	if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
206 		return ret;
207 
208 	*buf_id = f.fb_id;
209 	return 0;
210 }
211 
drmModeRmFB(int fd,uint32_t bufferId)212 int drmModeRmFB(int fd, uint32_t bufferId)
213 {
214 	return drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
215 
216 
217 }
218 
drmModeGetFB(int fd,uint32_t buf)219 drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
220 {
221 	struct drm_mode_fb_cmd info;
222 	drmModeFBPtr r;
223 
224 	info.fb_id = buf;
225 
226 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info))
227 		return NULL;
228 
229 	if (!(r = drmMalloc(sizeof(*r))))
230 		return NULL;
231 
232 	r->fb_id = info.fb_id;
233 	r->width = info.width;
234 	r->height = info.height;
235 	r->pitch = info.pitch;
236 	r->bpp = info.bpp;
237 	r->handle = info.handle;
238 	r->depth = info.depth;
239 
240 	return r;
241 }
242 
243 
244 /*
245  * Crtc functions
246  */
247 
drmModeGetCrtc(int fd,uint32_t crtcId)248 drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
249 {
250 	struct drm_mode_crtc crtc;
251 	drmModeCrtcPtr r;
252 
253 	crtc.crtc_id = crtcId;
254 
255 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
256 		return 0;
257 
258 	/*
259 	 * return
260 	 */
261 
262 	if (!(r = drmMalloc(sizeof(*r))))
263 		return 0;
264 
265 	r->crtc_id         = crtc.crtc_id;
266 	r->x               = crtc.x;
267 	r->y               = crtc.y;
268 	r->mode_valid      = crtc.mode_valid;
269 	if (r->mode_valid)
270 		memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
271 	r->buffer_id       = crtc.fb_id;
272 	r->gamma_size      = crtc.gamma_size;
273 	return r;
274 }
275 
276 
drmModeSetCrtc(int fd,uint32_t crtcId,uint32_t bufferId,uint32_t x,uint32_t y,uint32_t * connectors,int count,drmModeModeInfoPtr mode)277 int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
278                    uint32_t x, uint32_t y, uint32_t *connectors, int count,
279 		   drmModeModeInfoPtr mode)
280 {
281 	struct drm_mode_crtc crtc;
282 
283 	crtc.x             = x;
284 	crtc.y             = y;
285 	crtc.crtc_id       = crtcId;
286 	crtc.fb_id         = bufferId;
287 	crtc.set_connectors_ptr = VOID2U64(connectors);
288 	crtc.count_connectors = count;
289 	if (mode) {
290 	  memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
291 	  crtc.mode_valid = 1;
292 	} else
293 	  crtc.mode_valid = 0;
294 
295 	return drmIoctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
296 }
297 
298 /*
299  * Cursor manipulation
300  */
301 
drmModeSetCursor(int fd,uint32_t crtcId,uint32_t bo_handle,uint32_t width,uint32_t height)302 int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
303 {
304 	struct drm_mode_cursor arg;
305 
306 	arg.flags = DRM_MODE_CURSOR_BO;
307 	arg.crtc_id = crtcId;
308 	arg.width = width;
309 	arg.height = height;
310 	arg.handle = bo_handle;
311 
312 	return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
313 }
314 
drmModeMoveCursor(int fd,uint32_t crtcId,int x,int y)315 int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
316 {
317 	struct drm_mode_cursor arg;
318 
319 	arg.flags = DRM_MODE_CURSOR_MOVE;
320 	arg.crtc_id = crtcId;
321 	arg.x = x;
322 	arg.y = y;
323 
324 	return drmIoctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
325 }
326 
327 /*
328  * Encoder get
329  */
drmModeGetEncoder(int fd,uint32_t encoder_id)330 drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
331 {
332 	struct drm_mode_get_encoder enc;
333 	drmModeEncoderPtr r = NULL;
334 
335 	enc.encoder_id = encoder_id;
336 	enc.encoder_type = 0;
337 	enc.possible_crtcs = 0;
338 	enc.possible_clones = 0;
339 
340 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
341 		return 0;
342 
343 	if (!(r = drmMalloc(sizeof(*r))))
344 		return 0;
345 
346 	r->encoder_id = enc.encoder_id;
347 	r->crtc_id = enc.crtc_id;
348 	r->encoder_type = enc.encoder_type;
349 	r->possible_crtcs = enc.possible_crtcs;
350 	r->possible_clones = enc.possible_clones;
351 
352 	return r;
353 }
354 
355 /*
356  * Connector manipulation
357  */
358 
drmModeGetConnector(int fd,uint32_t connector_id)359 drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
360 {
361 	struct drm_mode_get_connector conn, counts;
362 	drmModeConnectorPtr r = NULL;
363 
364 retry:
365 	memset(&conn, 0, sizeof(struct drm_mode_get_connector));
366 	conn.connector_id = connector_id;
367 
368 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
369 		return 0;
370 
371 	counts = conn;
372 
373 	if (conn.count_props) {
374 		conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
375 		if (!conn.props_ptr)
376 			goto err_allocs;
377 		conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
378 		if (!conn.prop_values_ptr)
379 			goto err_allocs;
380 	}
381 
382 	if (conn.count_modes) {
383 		conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
384 		if (!conn.modes_ptr)
385 			goto err_allocs;
386 	}
387 
388 	if (conn.count_encoders) {
389 		conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
390 		if (!conn.encoders_ptr)
391 			goto err_allocs;
392 	}
393 
394 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
395 		goto err_allocs;
396 
397 	/* The number of available connectors and etc may have changed with a
398 	 * hotplug event in between the ioctls, in which case the field is
399 	 * silently ignored by the kernel.
400 	 */
401 	if (counts.count_props < conn.count_props ||
402 	    counts.count_modes < conn.count_modes ||
403 	    counts.count_encoders < conn.count_encoders) {
404 		drmFree(U642VOID(conn.props_ptr));
405 		drmFree(U642VOID(conn.prop_values_ptr));
406 		drmFree(U642VOID(conn.modes_ptr));
407 		drmFree(U642VOID(conn.encoders_ptr));
408 
409 		goto retry;
410 	}
411 
412 	if(!(r = drmMalloc(sizeof(*r)))) {
413 		goto err_allocs;
414 	}
415 
416 	r->connector_id = conn.connector_id;
417 	r->encoder_id = conn.encoder_id;
418 	r->connection   = conn.connection;
419 	r->mmWidth      = conn.mm_width;
420 	r->mmHeight     = conn.mm_height;
421 	/* convert subpixel from kernel to userspace */
422 	r->subpixel     = conn.subpixel + 1;
423 	r->count_modes  = conn.count_modes;
424 	r->count_props  = conn.count_props;
425 	r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
426 	r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
427 	r->modes        = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
428 	r->count_encoders = conn.count_encoders;
429 	r->encoders     = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
430 	r->connector_type  = conn.connector_type;
431 	r->connector_type_id = conn.connector_type_id;
432 
433 	if ((r->count_props && !r->props) ||
434 	    (r->count_props && !r->prop_values) ||
435 	    (r->count_modes && !r->modes) ||
436 	    (r->count_encoders && !r->encoders)) {
437 		drmFree(r->props);
438 		drmFree(r->prop_values);
439 		drmFree(r->modes);
440 		drmFree(r->encoders);
441 		drmFree(r);
442 		r = 0;
443 	}
444 
445 err_allocs:
446 	drmFree(U642VOID(conn.prop_values_ptr));
447 	drmFree(U642VOID(conn.props_ptr));
448 	drmFree(U642VOID(conn.modes_ptr));
449 	drmFree(U642VOID(conn.encoders_ptr));
450 
451 	return r;
452 }
453 
drmModeAttachMode(int fd,uint32_t connector_id,drmModeModeInfoPtr mode_info)454 int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
455 {
456 	struct drm_mode_mode_cmd res;
457 
458 	memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
459 	res.connector_id = connector_id;
460 
461 	return drmIoctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
462 }
463 
drmModeDetachMode(int fd,uint32_t connector_id,drmModeModeInfoPtr mode_info)464 int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
465 {
466 	struct drm_mode_mode_cmd res;
467 
468 	memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
469 	res.connector_id = connector_id;
470 
471 	return drmIoctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
472 }
473 
474 
drmModeGetProperty(int fd,uint32_t property_id)475 drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
476 {
477 	struct drm_mode_get_property prop;
478 	drmModePropertyPtr r;
479 
480 	prop.prop_id = property_id;
481 	prop.count_enum_blobs = 0;
482 	prop.count_values = 0;
483 	prop.flags = 0;
484 	prop.enum_blob_ptr = 0;
485 	prop.values_ptr = 0;
486 
487 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
488 		return 0;
489 
490 	if (prop.count_values)
491 		prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
492 
493 	if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
494 		prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
495 
496 	if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
497 		prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
498 		prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
499 	}
500 
501 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
502 		r = NULL;
503 		goto err_allocs;
504 	}
505 
506 	if (!(r = drmMalloc(sizeof(*r))))
507 		return NULL;
508 
509 	r->prop_id = prop.prop_id;
510 	r->count_values = prop.count_values;
511 
512 	r->flags = prop.flags;
513 	if (prop.count_values)
514 		r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
515 	if (prop.flags & DRM_MODE_PROP_ENUM) {
516 		r->count_enums = prop.count_enum_blobs;
517 		r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
518 	} else if (prop.flags & DRM_MODE_PROP_BLOB) {
519 		r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
520 		r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
521 		r->count_blobs = prop.count_enum_blobs;
522 	}
523 	strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
524 	r->name[DRM_PROP_NAME_LEN-1] = 0;
525 
526 err_allocs:
527 	drmFree(U642VOID(prop.values_ptr));
528 	drmFree(U642VOID(prop.enum_blob_ptr));
529 
530 	return r;
531 }
532 
drmModeFreeProperty(drmModePropertyPtr ptr)533 void drmModeFreeProperty(drmModePropertyPtr ptr)
534 {
535 	if (!ptr)
536 		return;
537 
538 	drmFree(ptr->values);
539 	drmFree(ptr->enums);
540 	drmFree(ptr);
541 }
542 
drmModeGetPropertyBlob(int fd,uint32_t blob_id)543 drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
544 {
545 	struct drm_mode_get_blob blob;
546 	drmModePropertyBlobPtr r;
547 
548 	blob.length = 0;
549 	blob.data = 0;
550 	blob.blob_id = blob_id;
551 
552 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
553 		return NULL;
554 
555 	if (blob.length)
556 		blob.data = VOID2U64(drmMalloc(blob.length));
557 
558 	if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
559 		r = NULL;
560 		goto err_allocs;
561 	}
562 
563 	if (!(r = drmMalloc(sizeof(*r))))
564 		return NULL;
565 
566 	r->id = blob.blob_id;
567 	r->length = blob.length;
568 	r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
569 
570 err_allocs:
571 	drmFree(U642VOID(blob.data));
572 	return r;
573 }
574 
drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)575 void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
576 {
577 	if (!ptr)
578 		return;
579 
580 	drmFree(ptr->data);
581 	drmFree(ptr);
582 }
583 
drmModeConnectorSetProperty(int fd,uint32_t connector_id,uint32_t property_id,uint64_t value)584 int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
585 			     uint64_t value)
586 {
587 	struct drm_mode_connector_set_property osp;
588 	int ret;
589 
590 	osp.connector_id = connector_id;
591 	osp.prop_id = property_id;
592 	osp.value = value;
593 
594 	if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
595 		return ret;
596 
597 	return 0;
598 }
599 
600 /*
601  * checks if a modesetting capable driver has attached to the pci id
602  * returns 0 if modesetting supported.
603  *  -EINVAL or invalid bus id
604  *  -ENOSYS if no modesetting support
605 */
drmCheckModesettingSupported(const char * busid)606 int drmCheckModesettingSupported(const char *busid)
607 {
608 #ifdef __linux__
609 	char pci_dev_dir[1024];
610 	int domain, bus, dev, func;
611 	DIR *sysdir;
612 	struct dirent *dent;
613 	int found = 0, ret;
614 
615 	ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
616 	if (ret != 4)
617 		return -EINVAL;
618 
619 	sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
620 		domain, bus, dev, func);
621 
622 	sysdir = opendir(pci_dev_dir);
623 	if (sysdir) {
624 		dent = readdir(sysdir);
625 		while (dent) {
626 			if (!strncmp(dent->d_name, "controlD", 8)) {
627 				found = 1;
628 				break;
629 			}
630 
631 			dent = readdir(sysdir);
632 		}
633 		closedir(sysdir);
634 		if (found)
635 			return 0;
636 	}
637 
638 	sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
639 		domain, bus, dev, func);
640 
641 	sysdir = opendir(pci_dev_dir);
642 	if (!sysdir)
643 		return -EINVAL;
644 
645 	dent = readdir(sysdir);
646 	while (dent) {
647 		if (!strncmp(dent->d_name, "drm:controlD", 12)) {
648 			found = 1;
649 			break;
650 		}
651 
652 		dent = readdir(sysdir);
653 	}
654 
655 	closedir(sysdir);
656 	if (found)
657 		return 0;
658 #endif
659 	return -ENOSYS;
660 
661 }
662 
drmModeCrtcGetGamma(int fd,uint32_t crtc_id,uint32_t size,uint16_t * red,uint16_t * green,uint16_t * blue)663 int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
664 			uint16_t *red, uint16_t *green, uint16_t *blue)
665 {
666 	int ret;
667 	struct drm_mode_crtc_lut l;
668 
669 	l.crtc_id = crtc_id;
670 	l.gamma_size = size;
671 	l.red = VOID2U64(red);
672 	l.green = VOID2U64(green);
673 	l.blue = VOID2U64(blue);
674 
675 	if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l)))
676 		return ret;
677 
678 	return 0;
679 }
680 
drmModeCrtcSetGamma(int fd,uint32_t crtc_id,uint32_t size,uint16_t * red,uint16_t * green,uint16_t * blue)681 int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
682 			uint16_t *red, uint16_t *green, uint16_t *blue)
683 {
684 	int ret;
685 	struct drm_mode_crtc_lut l;
686 
687 	l.crtc_id = crtc_id;
688 	l.gamma_size = size;
689 	l.red = VOID2U64(red);
690 	l.green = VOID2U64(green);
691 	l.blue = VOID2U64(blue);
692 
693 	if ((ret = drmIoctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l)))
694 		return ret;
695 
696 	return 0;
697 }
698