OSDN Git Service

libdrm: update drm headers from kernel, including new overlay ioctls & structs
[android-x86/external-libdrm.git] / xf86drmMode.c
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 <unistd.h>
50 #include <errno.h>
51
52 #define U642VOID(x) ((void *)(unsigned long)(x))
53 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
54
55 static inline int DRM_IOCTL(int fd, unsigned long cmd, void *arg)
56 {
57         int ret = drmIoctl(fd, cmd, arg);
58         return ret < 0 ? -errno : ret;
59 }
60
61 /*
62  * Util functions
63  */
64
65 void* drmAllocCpy(void *array, int count, int entry_size)
66 {
67         char *r;
68         int i;
69
70         if (!count || !array || !entry_size)
71                 return 0;
72
73         if (!(r = drmMalloc(count*entry_size)))
74                 return 0;
75
76         for (i = 0; i < count; i++)
77                 memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
78
79         return r;
80 }
81
82 /*
83  * A couple of free functions.
84  */
85
86 void drmModeFreeModeInfo(drmModeModeInfoPtr ptr)
87 {
88         if (!ptr)
89                 return;
90
91         drmFree(ptr);
92 }
93
94 void drmModeFreeResources(drmModeResPtr ptr)
95 {
96         if (!ptr)
97                 return;
98
99         drmFree(ptr);
100
101 }
102
103 void drmModeFreeFB(drmModeFBPtr ptr)
104 {
105         if (!ptr)
106                 return;
107
108         /* we might add more frees later. */
109         drmFree(ptr);
110 }
111
112 void drmModeFreeCrtc(drmModeCrtcPtr ptr)
113 {
114         if (!ptr)
115                 return;
116
117         drmFree(ptr);
118
119 }
120
121 void drmModeFreeConnector(drmModeConnectorPtr ptr)
122 {
123         if (!ptr)
124                 return;
125
126         drmFree(ptr->encoders);
127         drmFree(ptr->prop_values);
128         drmFree(ptr->props);
129         drmFree(ptr->modes);
130         drmFree(ptr);
131
132 }
133
134 void drmModeFreeEncoder(drmModeEncoderPtr ptr)
135 {
136         drmFree(ptr);
137 }
138
139 /*
140  * ModeSetting functions.
141  */
142
143 drmModeResPtr drmModeGetResources(int fd)
144 {
145         struct drm_mode_card_res res, counts;
146         drmModeResPtr r = 0;
147
148 retry:
149         memset(&res, 0, sizeof(struct drm_mode_card_res));
150         if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
151                 return 0;
152
153         counts = res;
154
155         if (res.count_fbs) {
156                 res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
157                 if (!res.fb_id_ptr)
158                         goto err_allocs;
159         }
160         if (res.count_crtcs) {
161                 res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
162                 if (!res.crtc_id_ptr)
163                         goto err_allocs;
164         }
165         if (res.count_connectors) {
166                 res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
167                 if (!res.connector_id_ptr)
168                         goto err_allocs;
169         }
170         if (res.count_encoders) {
171                 res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
172                 if (!res.encoder_id_ptr)
173                         goto err_allocs;
174         }
175
176         if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
177                 goto err_allocs;
178
179         /* The number of available connectors and etc may have changed with a
180          * hotplug event in between the ioctls, in which case the field is
181          * silently ignored by the kernel.
182          */
183         if (counts.count_fbs < res.count_fbs ||
184             counts.count_crtcs < res.count_crtcs ||
185             counts.count_connectors < res.count_connectors ||
186             counts.count_encoders < res.count_encoders)
187         {
188                 drmFree(U642VOID(res.fb_id_ptr));
189                 drmFree(U642VOID(res.crtc_id_ptr));
190                 drmFree(U642VOID(res.connector_id_ptr));
191                 drmFree(U642VOID(res.encoder_id_ptr));
192
193                 goto retry;
194         }
195
196         /*
197          * return
198          */
199         if (!(r = drmMalloc(sizeof(*r))))
200                 goto err_allocs;
201
202         r->min_width     = res.min_width;
203         r->max_width     = res.max_width;
204         r->min_height    = res.min_height;
205         r->max_height    = res.max_height;
206         r->count_fbs     = res.count_fbs;
207         r->count_crtcs   = res.count_crtcs;
208         r->count_connectors = res.count_connectors;
209         r->count_encoders = res.count_encoders;
210
211         r->fbs        = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
212         r->crtcs      = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
213         r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
214         r->encoders   = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
215         if ((res.count_fbs && !r->fbs) ||
216             (res.count_crtcs && !r->crtcs) ||
217             (res.count_connectors && !r->connectors) ||
218             (res.count_encoders && !r->encoders))
219         {
220                 drmFree(r->fbs);
221                 drmFree(r->crtcs);
222                 drmFree(r->connectors);
223                 drmFree(r->encoders);
224                 drmFree(r);
225                 r = 0;
226         }
227
228 err_allocs:
229         drmFree(U642VOID(res.fb_id_ptr));
230         drmFree(U642VOID(res.crtc_id_ptr));
231         drmFree(U642VOID(res.connector_id_ptr));
232         drmFree(U642VOID(res.encoder_id_ptr));
233
234         return r;
235 }
236
237 int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
238                  uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
239                  uint32_t *buf_id)
240 {
241         struct drm_mode_fb_cmd f;
242         int ret;
243
244         f.width  = width;
245         f.height = height;
246         f.pitch  = pitch;
247         f.bpp    = bpp;
248         f.depth  = depth;
249         f.handle = bo_handle;
250
251         if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB, &f)))
252                 return ret;
253
254         *buf_id = f.fb_id;
255         return 0;
256 }
257
258 int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
259                   uint32_t pixel_format, uint32_t bo_handles[4],
260                   uint32_t pitches[4], uint32_t offsets[4],
261                   uint32_t *buf_id, uint32_t flags)
262 {
263         struct drm_mode_fb_cmd2 f;
264         int ret;
265
266         f.width  = width;
267         f.height = height;
268         f.pixel_format = pixel_format;
269         f.flags = flags;
270         memcpy(f.handles, bo_handles, sizeof(bo_handles));
271         memcpy(f.pitches, pitches, sizeof(pitches));
272         memcpy(f.offsets, offsets, sizeof(offsets));
273
274         if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB2, &f)))
275                 return ret;
276
277         *buf_id = f.fb_id;
278         return 0;
279 }
280
281 int drmModeRmFB(int fd, uint32_t bufferId)
282 {
283         return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
284
285
286 }
287
288 drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
289 {
290         struct drm_mode_fb_cmd info;
291         drmModeFBPtr r;
292
293         info.fb_id = buf;
294
295         if (drmIoctl(fd, DRM_IOCTL_MODE_GETFB, &info))
296                 return NULL;
297
298         if (!(r = drmMalloc(sizeof(*r))))
299                 return NULL;
300
301         r->fb_id = info.fb_id;
302         r->width = info.width;
303         r->height = info.height;
304         r->pitch = info.pitch;
305         r->bpp = info.bpp;
306         r->handle = info.handle;
307         r->depth = info.depth;
308
309         return r;
310 }
311
312 int drmModeDirtyFB(int fd, uint32_t bufferId,
313                    drmModeClipPtr clips, uint32_t num_clips)
314 {
315         struct drm_mode_fb_dirty_cmd dirty = { 0 };
316
317         dirty.fb_id = bufferId;
318         dirty.clips_ptr = VOID2U64(clips);
319         dirty.num_clips = num_clips;
320
321         return DRM_IOCTL(fd, DRM_IOCTL_MODE_DIRTYFB, &dirty);
322 }
323
324
325 /*
326  * Crtc functions
327  */
328
329 drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
330 {
331         struct drm_mode_crtc crtc;
332         drmModeCrtcPtr r;
333
334         crtc.crtc_id = crtcId;
335
336         if (drmIoctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
337                 return 0;
338
339         /*
340          * return
341          */
342
343         if (!(r = drmMalloc(sizeof(*r))))
344                 return 0;
345
346         r->crtc_id         = crtc.crtc_id;
347         r->x               = crtc.x;
348         r->y               = crtc.y;
349         r->mode_valid      = crtc.mode_valid;
350         if (r->mode_valid)
351                 memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
352         r->buffer_id       = crtc.fb_id;
353         r->gamma_size      = crtc.gamma_size;
354         return r;
355 }
356
357
358 int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
359                    uint32_t x, uint32_t y, uint32_t *connectors, int count,
360                    drmModeModeInfoPtr mode)
361 {
362         struct drm_mode_crtc crtc;
363
364         crtc.x             = x;
365         crtc.y             = y;
366         crtc.crtc_id       = crtcId;
367         crtc.fb_id         = bufferId;
368         crtc.set_connectors_ptr = VOID2U64(connectors);
369         crtc.count_connectors = count;
370         if (mode) {
371           memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
372           crtc.mode_valid = 1;
373         } else
374           crtc.mode_valid = 0;
375
376         return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
377 }
378
379 /*
380  * Cursor manipulation
381  */
382
383 int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
384 {
385         struct drm_mode_cursor arg;
386
387         arg.flags = DRM_MODE_CURSOR_BO;
388         arg.crtc_id = crtcId;
389         arg.width = width;
390         arg.height = height;
391         arg.handle = bo_handle;
392
393         return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg);
394 }
395
396 int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
397 {
398         struct drm_mode_cursor arg;
399
400         arg.flags = DRM_MODE_CURSOR_MOVE;
401         arg.crtc_id = crtcId;
402         arg.x = x;
403         arg.y = y;
404
405         return DRM_IOCTL(fd, DRM_IOCTL_MODE_CURSOR, &arg);
406 }
407
408 /*
409  * Encoder get
410  */
411 drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
412 {
413         struct drm_mode_get_encoder enc;
414         drmModeEncoderPtr r = NULL;
415
416         enc.encoder_id = encoder_id;
417         enc.encoder_type = 0;
418         enc.possible_crtcs = 0;
419         enc.possible_clones = 0;
420
421         if (drmIoctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
422                 return 0;
423
424         if (!(r = drmMalloc(sizeof(*r))))
425                 return 0;
426
427         r->encoder_id = enc.encoder_id;
428         r->crtc_id = enc.crtc_id;
429         r->encoder_type = enc.encoder_type;
430         r->possible_crtcs = enc.possible_crtcs;
431         r->possible_clones = enc.possible_clones;
432
433         return r;
434 }
435
436 /*
437  * Connector manipulation
438  */
439
440 drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
441 {
442         struct drm_mode_get_connector conn, counts;
443         drmModeConnectorPtr r = NULL;
444
445 retry:
446         memset(&conn, 0, sizeof(struct drm_mode_get_connector));
447         conn.connector_id = connector_id;
448
449         if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
450                 return 0;
451
452         counts = conn;
453
454         if (conn.count_props) {
455                 conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
456                 if (!conn.props_ptr)
457                         goto err_allocs;
458                 conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
459                 if (!conn.prop_values_ptr)
460                         goto err_allocs;
461         }
462
463         if (conn.count_modes) {
464                 conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
465                 if (!conn.modes_ptr)
466                         goto err_allocs;
467         }
468
469         if (conn.count_encoders) {
470                 conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
471                 if (!conn.encoders_ptr)
472                         goto err_allocs;
473         }
474
475         if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
476                 goto err_allocs;
477
478         /* The number of available connectors and etc may have changed with a
479          * hotplug event in between the ioctls, in which case the field is
480          * silently ignored by the kernel.
481          */
482         if (counts.count_props < conn.count_props ||
483             counts.count_modes < conn.count_modes ||
484             counts.count_encoders < conn.count_encoders) {
485                 drmFree(U642VOID(conn.props_ptr));
486                 drmFree(U642VOID(conn.prop_values_ptr));
487                 drmFree(U642VOID(conn.modes_ptr));
488                 drmFree(U642VOID(conn.encoders_ptr));
489
490                 goto retry;
491         }
492
493         if(!(r = drmMalloc(sizeof(*r)))) {
494                 goto err_allocs;
495         }
496
497         r->connector_id = conn.connector_id;
498         r->encoder_id = conn.encoder_id;
499         r->connection   = conn.connection;
500         r->mmWidth      = conn.mm_width;
501         r->mmHeight     = conn.mm_height;
502         /* convert subpixel from kernel to userspace */
503         r->subpixel     = conn.subpixel + 1;
504         r->count_modes  = conn.count_modes;
505         r->count_props  = conn.count_props;
506         r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
507         r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
508         r->modes        = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
509         r->count_encoders = conn.count_encoders;
510         r->encoders     = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
511         r->connector_type  = conn.connector_type;
512         r->connector_type_id = conn.connector_type_id;
513
514         if ((r->count_props && !r->props) ||
515             (r->count_props && !r->prop_values) ||
516             (r->count_modes && !r->modes) ||
517             (r->count_encoders && !r->encoders)) {
518                 drmFree(r->props);
519                 drmFree(r->prop_values);
520                 drmFree(r->modes);
521                 drmFree(r->encoders);
522                 drmFree(r);
523                 r = 0;
524         }
525
526 err_allocs:
527         drmFree(U642VOID(conn.prop_values_ptr));
528         drmFree(U642VOID(conn.props_ptr));
529         drmFree(U642VOID(conn.modes_ptr));
530         drmFree(U642VOID(conn.encoders_ptr));
531
532         return r;
533 }
534
535 int drmModeAttachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
536 {
537         struct drm_mode_mode_cmd res;
538
539         memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
540         res.connector_id = connector_id;
541
542         return DRM_IOCTL(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
543 }
544
545 int drmModeDetachMode(int fd, uint32_t connector_id, drmModeModeInfoPtr mode_info)
546 {
547         struct drm_mode_mode_cmd res;
548
549         memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
550         res.connector_id = connector_id;
551
552         return DRM_IOCTL(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
553 }
554
555
556 drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
557 {
558         struct drm_mode_get_property prop;
559         drmModePropertyPtr r;
560
561         prop.prop_id = property_id;
562         prop.count_enum_blobs = 0;
563         prop.count_values = 0;
564         prop.flags = 0;
565         prop.enum_blob_ptr = 0;
566         prop.values_ptr = 0;
567
568         if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
569                 return 0;
570
571         if (prop.count_values)
572                 prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
573
574         if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
575                 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
576
577         if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
578                 prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
579                 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
580         }
581
582         if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
583                 r = NULL;
584                 goto err_allocs;
585         }
586
587         if (!(r = drmMalloc(sizeof(*r))))
588                 return NULL;
589
590         r->prop_id = prop.prop_id;
591         r->count_values = prop.count_values;
592
593         r->flags = prop.flags;
594         if (prop.count_values)
595                 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
596         if (prop.flags & DRM_MODE_PROP_ENUM) {
597                 r->count_enums = prop.count_enum_blobs;
598                 r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
599         } else if (prop.flags & DRM_MODE_PROP_BLOB) {
600                 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
601                 r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
602                 r->count_blobs = prop.count_enum_blobs;
603         }
604         strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
605         r->name[DRM_PROP_NAME_LEN-1] = 0;
606
607 err_allocs:
608         drmFree(U642VOID(prop.values_ptr));
609         drmFree(U642VOID(prop.enum_blob_ptr));
610
611         return r;
612 }
613
614 void drmModeFreeProperty(drmModePropertyPtr ptr)
615 {
616         if (!ptr)
617                 return;
618
619         drmFree(ptr->values);
620         drmFree(ptr->enums);
621         drmFree(ptr);
622 }
623
624 drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
625 {
626         struct drm_mode_get_blob blob;
627         drmModePropertyBlobPtr r;
628
629         blob.length = 0;
630         blob.data = 0;
631         blob.blob_id = blob_id;
632
633         if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
634                 return NULL;
635
636         if (blob.length)
637                 blob.data = VOID2U64(drmMalloc(blob.length));
638
639         if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
640                 r = NULL;
641                 goto err_allocs;
642         }
643
644         if (!(r = drmMalloc(sizeof(*r))))
645                 goto err_allocs;
646
647         r->id = blob.blob_id;
648         r->length = blob.length;
649         r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
650
651 err_allocs:
652         drmFree(U642VOID(blob.data));
653         return r;
654 }
655
656 void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
657 {
658         if (!ptr)
659                 return;
660
661         drmFree(ptr->data);
662         drmFree(ptr);
663 }
664
665 int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
666                              uint64_t value)
667 {
668         struct drm_mode_connector_set_property osp;
669
670         osp.connector_id = connector_id;
671         osp.prop_id = property_id;
672         osp.value = value;
673
674         return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp);
675 }
676
677 /*
678  * checks if a modesetting capable driver has attached to the pci id
679  * returns 0 if modesetting supported.
680  *  -EINVAL or invalid bus id
681  *  -ENOSYS if no modesetting support
682 */
683 int drmCheckModesettingSupported(const char *busid)
684 {
685 #ifdef __linux__
686         char pci_dev_dir[1024];
687         int domain, bus, dev, func;
688         DIR *sysdir;
689         struct dirent *dent;
690         int found = 0, ret;
691
692         ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
693         if (ret != 4)
694                 return -EINVAL;
695
696         sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
697                 domain, bus, dev, func);
698
699         sysdir = opendir(pci_dev_dir);
700         if (sysdir) {
701                 dent = readdir(sysdir);
702                 while (dent) {
703                         if (!strncmp(dent->d_name, "controlD", 8)) {
704                                 found = 1;
705                                 break;
706                         }
707
708                         dent = readdir(sysdir);
709                 }
710                 closedir(sysdir);
711                 if (found)
712                         return 0;
713         }
714
715         sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
716                 domain, bus, dev, func);
717
718         sysdir = opendir(pci_dev_dir);
719         if (!sysdir)
720                 return -EINVAL;
721
722         dent = readdir(sysdir);
723         while (dent) {
724                 if (!strncmp(dent->d_name, "drm:controlD", 12)) {
725                         found = 1;
726                         break;
727                 }
728
729                 dent = readdir(sysdir);
730         }
731
732         closedir(sysdir);
733         if (found)
734                 return 0;
735 #endif
736         return -ENOSYS;
737
738 }
739
740 int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
741                         uint16_t *red, uint16_t *green, uint16_t *blue)
742 {
743         struct drm_mode_crtc_lut l;
744
745         l.crtc_id = crtc_id;
746         l.gamma_size = size;
747         l.red = VOID2U64(red);
748         l.green = VOID2U64(green);
749         l.blue = VOID2U64(blue);
750
751         return DRM_IOCTL(fd, DRM_IOCTL_MODE_GETGAMMA, &l);
752 }
753
754 int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
755                         uint16_t *red, uint16_t *green, uint16_t *blue)
756 {
757         struct drm_mode_crtc_lut l;
758
759         l.crtc_id = crtc_id;
760         l.gamma_size = size;
761         l.red = VOID2U64(red);
762         l.green = VOID2U64(green);
763         l.blue = VOID2U64(blue);
764
765         return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l);
766 }
767
768 int drmHandleEvent(int fd, drmEventContextPtr evctx)
769 {
770         char buffer[1024];
771         int len, i;
772         struct drm_event *e;
773         struct drm_event_vblank *vblank;
774         
775         /* The DRM read semantics guarantees that we always get only
776          * complete events. */
777
778         len = read(fd, buffer, sizeof buffer);
779         if (len == 0)
780                 return 0;
781         if (len < sizeof *e)
782                 return -1;
783
784         i = 0;
785         while (i < len) {
786                 e = (struct drm_event *) &buffer[i];
787                 switch (e->type) {
788                 case DRM_EVENT_VBLANK:
789                         if (evctx->version < 1 ||
790                             evctx->vblank_handler == NULL)
791                                 break;
792                         vblank = (struct drm_event_vblank *) e;
793                         evctx->vblank_handler(fd,
794                                               vblank->sequence, 
795                                               vblank->tv_sec,
796                                               vblank->tv_usec,
797                                               U642VOID (vblank->user_data));
798                         break;
799                 case DRM_EVENT_FLIP_COMPLETE:
800                         if (evctx->version < 2 ||
801                             evctx->page_flip_handler == NULL)
802                                 break;
803                         vblank = (struct drm_event_vblank *) e;
804                         evctx->page_flip_handler(fd,
805                                                  vblank->sequence,
806                                                  vblank->tv_sec,
807                                                  vblank->tv_usec,
808                                                  U642VOID (vblank->user_data));
809                         break;
810                 default:
811                         break;
812                 }
813                 i += e->length;
814         }
815
816         return 0;
817 }
818
819 int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
820                     uint32_t flags, void *user_data)
821 {
822         struct drm_mode_crtc_page_flip flip;
823
824         flip.fb_id = fb_id;
825         flip.crtc_id = crtc_id;
826         flip.user_data = VOID2U64(user_data);
827         flip.flags = flags;
828         flip.reserved = 0;
829
830         return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
831 }
832
833 int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id,
834                     uint32_t fb_id, uint32_t flags,
835                     uint32_t crtc_x, uint32_t crtc_y,
836                     uint32_t crtc_w, uint32_t crtc_h,
837                     uint32_t src_x, uint32_t src_y,
838                     uint32_t src_w, uint32_t src_h)
839
840 {
841         struct drm_mode_set_plane s;
842
843         s.plane_id = plane_id;
844         s.crtc_id = crtc_id;
845         s.fb_id = fb_id;
846         s.flags = flags;
847         s.crtc_x = crtc_x;
848         s.crtc_y = crtc_y;
849         s.crtc_w = crtc_w;
850         s.crtc_h = crtc_h;
851         s.src_x = src_x;
852         s.src_y = src_y;
853         s.src_w = src_w;
854         s.src_h = src_h;
855
856         return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETPLANE, &s);
857 }
858
859
860 drmModePlanePtr drmModeGetPlane(int fd, uint32_t plane_id)
861 {
862         struct drm_mode_get_plane ovr, counts;
863         drmModePlanePtr r = 0;
864
865 retry:
866         memset(&ovr, 0, sizeof(struct drm_mode_get_plane));
867         ovr.plane_id = plane_id;
868         if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr))
869                 return 0;
870
871         counts = ovr;
872
873         if (ovr.count_format_types) {
874                 ovr.format_type_ptr = VOID2U64(drmMalloc(ovr.count_format_types *
875                                                          sizeof(uint32_t)));
876                 if (!ovr.format_type_ptr)
877                         goto err_allocs;
878         }
879
880         if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANE, &ovr))
881                 goto err_allocs;
882
883         if (counts.count_format_types < ovr.count_format_types) {
884                 drmFree(U642VOID(ovr.format_type_ptr));
885                 goto retry;
886         }
887
888         if (!(r = drmMalloc(sizeof(*r))))
889                 goto err_allocs;
890
891         r->count_formats = ovr.count_format_types;
892         r->plane_id = ovr.plane_id;
893         r->crtc_id = ovr.crtc_id;
894         r->fb_id = ovr.fb_id;
895         r->possible_crtcs = ovr.possible_crtcs;
896         r->gamma_size = ovr.gamma_size;
897         r->formats = drmAllocCpy(U642VOID(ovr.format_type_ptr),
898                                  ovr.count_format_types, sizeof(uint32_t));
899         if (ovr.count_format_types && !r->formats) {
900                 drmFree(r->formats);
901                 r = 0;
902         }
903
904 err_allocs:
905         drmFree(U642VOID(ovr.format_type_ptr));
906
907         return r;
908 }
909
910 void drmModeFreePlane(drmModePlanePtr ptr)
911 {
912         if (!ptr)
913                 return;
914
915         drmFree(ptr->formats);
916         drmFree(ptr);
917 }
918
919 drmModePlaneResPtr drmModeGetPlaneResources(int fd)
920 {
921         struct drm_mode_get_plane_res res, counts;
922         drmModePlaneResPtr r = 0;
923
924 retry:
925         memset(&res, 0, sizeof(struct drm_mode_get_plane_res));
926         if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res))
927                 return 0;
928
929         counts = res;
930
931         if (res.count_planes) {
932                 res.plane_id_ptr = VOID2U64(drmMalloc(res.count_planes *
933                                                         sizeof(uint32_t)));
934                 if (!res.plane_id_ptr)
935                         goto err_allocs;
936         }
937
938         if (drmIoctl(fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &res))
939                 goto err_allocs;
940
941         if (counts.count_planes < res.count_planes) {
942                 drmFree(U642VOID(res.plane_id_ptr));
943                 goto retry;
944         }
945
946         if (!(r = drmMalloc(sizeof(*r))))
947                 goto err_allocs;
948
949         r->count_planes = res.count_planes;
950         r->planes = drmAllocCpy(U642VOID(res.plane_id_ptr),
951                                   res.count_planes, sizeof(uint32_t));
952         if (res.count_planes && !r->planes) {
953                 drmFree(r->planes);
954                 r = 0;
955         }
956
957 err_allocs:
958         drmFree(U642VOID(res.plane_id_ptr));
959
960         return r;
961 }