drm: add master set/drop protocol
[profile/ivi/libdrm.git] / libdrm / 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) <year> <copyright holders>
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included in
22  * all copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * IN THE SOFTWARE.
31  *
32  */
33
34 /*
35  * TODO the types we are after are defined in diffrent headers on diffrent
36  * platforms find which headers to include to get uint32_t
37  */
38 #include <stdint.h>
39 #include <sys/ioctl.h>
40 #include <stdio.h>
41
42 #include "xf86drmMode.h"
43 #include "xf86drm.h"
44 #include <drm.h>
45 #include <string.h>
46 #include <dirent.h>
47 #include <errno.h>
48
49 #define U642VOID(x) ((void *)(unsigned long)(x))
50 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
51
52 /*
53  * Util functions
54  */
55
56 void* drmAllocCpy(void *array, int count, int entry_size)
57 {
58         char *r;
59         int i;
60
61         if (!count || !array || !entry_size)
62                 return 0;
63
64         if (!(r = drmMalloc(count*entry_size)))
65                 return 0;
66
67         for (i = 0; i < count; i++)
68                 memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
69
70         return r;
71 }
72
73 /*
74  * A couple of free functions.
75  */
76
77 void drmModeFreeModeInfo(struct drm_mode_modeinfo *ptr)
78 {
79         if (!ptr)
80                 return;
81
82         drmFree(ptr);
83 }
84
85 void drmModeFreeResources(drmModeResPtr ptr)
86 {
87         if (!ptr)
88                 return;
89
90         drmFree(ptr);
91
92 }
93
94 void drmModeFreeFB(drmModeFBPtr ptr)
95 {
96         if (!ptr)
97                 return;
98
99         /* we might add more frees later. */
100         drmFree(ptr);
101 }
102
103 void drmModeFreeCrtc(drmModeCrtcPtr ptr)
104 {
105         if (!ptr)
106                 return;
107
108         drmFree(ptr);
109
110 }
111
112 void drmModeFreeOutput(drmModeOutputPtr ptr)
113 {
114         if (!ptr)
115                 return;
116
117         drmFree(ptr->modes);
118         drmFree(ptr);
119
120 }
121
122 /*
123  * ModeSetting functions.
124  */
125
126 drmModeResPtr drmModeGetResources(int fd)
127 {
128         struct drm_mode_card_res res;
129         drmModeResPtr r = 0;
130
131         memset(&res, 0, sizeof(struct drm_mode_card_res));
132
133         if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
134                 return 0;
135
136         if (res.count_fbs)
137                 res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
138         if (res.count_crtcs)
139                 res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
140         if (res.count_outputs)
141                 res.output_id_ptr = VOID2U64(drmMalloc(res.count_outputs*sizeof(uint32_t)));
142
143         if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
144                 r = NULL;
145                 goto err_allocs;
146         }
147
148         /*
149          * return
150          */
151
152
153         if (!(r = drmMalloc(sizeof(*r))))
154                 return 0;
155
156         r->min_width     = res.min_width;
157         r->max_width     = res.max_width;
158         r->min_height    = res.min_height;
159         r->max_height    = res.max_height;
160         r->count_fbs     = res.count_fbs;
161         r->count_crtcs   = res.count_crtcs;
162         r->count_outputs = res.count_outputs;
163         /* TODO we realy should test if these allocs fails. */
164         r->fbs           = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
165         r->crtcs         = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
166         r->outputs       = drmAllocCpy(U642VOID(res.output_id_ptr), res.count_outputs, sizeof(uint32_t));
167
168 err_allocs:
169         drmFree(U642VOID(res.fb_id_ptr));
170         drmFree(U642VOID(res.crtc_id_ptr));
171         drmFree(U642VOID(res.output_id_ptr));
172
173         return r;
174 }
175
176 uint32_t drmModeGetHotplug(int fd)
177 {
178         struct drm_mode_hotplug arg;
179         arg.counter = 0;
180
181         ioctl(fd, DRM_IOCTL_MODE_HOTPLUG, &arg);
182         return arg.counter;
183 }
184
185 int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
186                  uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
187                  uint32_t *buf_id)
188 {
189         struct drm_mode_fb_cmd f;
190         int ret;
191
192         f.width  = width;
193         f.height = height;
194         f.pitch  = pitch;
195         f.bpp    = bpp;
196         f.depth  = depth;
197         f.handle = bo_handle;
198
199         if ((ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
200                 return ret;
201
202         *buf_id = f.buffer_id;
203         return 0;
204 }
205
206 int drmModeRmFB(int fd, uint32_t bufferId)
207 {
208         return ioctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
209
210
211 }
212
213 drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
214 {
215         struct drm_mode_fb_cmd info;
216         drmModeFBPtr r;
217
218         info.buffer_id = buf;
219
220         if (ioctl(fd, DRM_IOCTL_MODE_GETFB, &info))
221                 return NULL;
222
223         if (!(r = drmMalloc(sizeof(*r))))
224                 return NULL;
225
226         r->buffer_id = info.buffer_id;
227         r->width = info.width;
228         r->height = info.height;
229         r->pitch = info.pitch;
230         r->bpp = info.bpp;
231         r->handle = info.handle;
232         r->depth = info.depth;
233
234         return r;
235 }
236
237
238 /*
239  * Crtc functions
240  */
241
242 drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
243 {
244         struct drm_mode_crtc crtc;
245         drmModeCrtcPtr r;
246
247         crtc.count_outputs   = 0;
248         crtc.outputs         = 0;
249         crtc.count_possibles = 0;
250         crtc.possibles       = 0;
251         crtc.crtc_id = crtcId;
252
253         if (ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
254                 return 0;
255
256         /*
257          * return
258          */
259
260         if (!(r = drmMalloc(sizeof(*r))))
261                 return 0;
262         
263         r->crtc_id         = crtc.crtc_id;
264         r->x               = crtc.x;
265         r->y               = crtc.y;
266         r->mode_valid      = crtc.mode_valid;
267         if (r->mode_valid)
268                 memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
269         r->buffer_id       = crtc.fb_id;
270         r->gamma_size      = crtc.gamma_size;
271         r->count_outputs   = crtc.count_outputs;
272         r->count_possibles = crtc.count_possibles;
273         /* TODO we realy should test if these alloc & cpy fails. */
274         r->outputs         = crtc.outputs;
275         r->possibles       = crtc.possibles;
276
277         return r;
278 }
279
280
281 int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
282                    uint32_t x, uint32_t y, uint32_t *outputs, int count,
283                    struct drm_mode_modeinfo *mode)
284 {
285         struct drm_mode_crtc crtc;
286
287         crtc.count_outputs   = 0;
288         crtc.outputs         = 0;
289         crtc.count_possibles = 0;
290         crtc.possibles       = 0;
291
292         crtc.x             = x;
293         crtc.y             = y;
294         crtc.crtc_id       = crtcId;
295         crtc.fb_id         = bufferId;
296         crtc.set_outputs_ptr = VOID2U64(outputs);
297         crtc.count_outputs = count;
298         if (mode) {
299           memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
300           crtc.mode_valid = 1;
301         } else
302           crtc.mode_valid = 0;
303
304         return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
305 }
306
307 /*
308  * Cursor manipulation
309  */
310
311 int drmModeSetCursor(int fd, uint32_t crtcId, drmBO *bo, uint32_t width, uint32_t height)
312 {
313         struct drm_mode_cursor arg;
314
315         arg.flags = DRM_MODE_CURSOR_BO;
316         arg.crtc = crtcId;
317         arg.width = width;
318         arg.height = height;
319         if (bo)
320                 arg.handle = bo->handle;
321         else
322                 arg.handle = 0;
323
324         return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
325 }
326
327 int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
328 {
329         struct drm_mode_cursor arg;
330
331         arg.flags = DRM_MODE_CURSOR_MOVE;
332         arg.crtc = crtcId;
333         arg.x = x;
334         arg.y = y;
335
336         return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
337 }
338
339 /*
340  * Output manipulation
341  */
342
343 drmModeOutputPtr drmModeGetOutput(int fd, uint32_t output_id)
344 {
345         struct drm_mode_get_output out;
346         drmModeOutputPtr r = NULL;
347
348         out.output = output_id;
349         out.output_type_id = 0;
350         out.output_type  = 0;
351         out.count_crtcs  = 0;
352         out.crtcs        = 0;
353         out.count_clones = 0;
354         out.clones       = 0;
355         out.count_modes  = 0;
356         out.modes_ptr    = 0;
357         out.count_props  = 0;
358         out.props_ptr    = 0;
359         out.prop_values_ptr = 0;
360
361         if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
362                 return 0;
363
364         if (out.count_props) {
365                 out.props_ptr = VOID2U64(drmMalloc(out.count_props*sizeof(uint32_t)));
366                 out.prop_values_ptr = VOID2U64(drmMalloc(out.count_props*sizeof(uint64_t)));
367         }
368
369         if (out.count_modes)
370                 out.modes_ptr = VOID2U64(drmMalloc(out.count_modes*sizeof(struct drm_mode_modeinfo)));
371
372         if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
373                 goto err_allocs;
374
375         if(!(r = drmMalloc(sizeof(*r)))) {
376                 goto err_allocs;
377         }
378
379         r->output_id = out.output;
380         r->crtc = out.crtc;
381         r->connection   = out.connection;
382         r->mmWidth      = out.mm_width;
383         r->mmHeight     = out.mm_height;
384         r->subpixel     = out.subpixel;
385         r->count_crtcs  = out.count_crtcs;
386         r->count_clones = out.count_clones;
387         r->count_modes  = out.count_modes;
388         /* TODO we should test if these alloc & cpy fails. */
389         r->crtcs        = out.crtcs;
390         r->clones       = out.clones;
391         r->count_props  = out.count_props;
392         r->props        = drmAllocCpy(U642VOID(out.props_ptr), out.count_props, sizeof(uint32_t));
393         r->prop_values  = drmAllocCpy(U642VOID(out.prop_values_ptr), out.count_props, sizeof(uint64_t));
394         r->modes        = drmAllocCpy(U642VOID(out.modes_ptr), out.count_modes, sizeof(struct drm_mode_modeinfo));
395         r->output_type  = out.output_type;
396         r->output_type_id = out.output_type_id;
397
398 err_allocs:
399         drmFree(U642VOID(out.prop_values_ptr));
400         drmFree(U642VOID(out.props_ptr));
401         drmFree(U642VOID(out.modes_ptr));
402
403         return r;
404 }
405
406 int drmModeAttachMode(int fd, uint32_t output_id, struct drm_mode_modeinfo *mode_info)
407 {
408         struct drm_mode_mode_cmd res;
409
410         memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
411         res.output_id = output_id;
412
413         return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
414 }
415
416 int drmModeDetachMode(int fd, uint32_t output_id, struct drm_mode_modeinfo *mode_info)
417 {
418         struct drm_mode_mode_cmd res;
419
420         memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
421         res.output_id = output_id;
422
423         return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
424 }
425
426
427 drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
428 {
429         struct drm_mode_get_property prop;
430         drmModePropertyPtr r;
431
432         prop.prop_id = property_id;
433         prop.count_enum_blobs = 0;
434         prop.count_values = 0;
435         prop.flags = 0;
436         prop.enum_blob_ptr = 0;
437         prop.values_ptr = 0;
438
439         if (ioctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
440                 return 0;
441
442         if (prop.count_values)
443                 prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
444
445         if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
446                 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
447
448         if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
449                 prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
450                 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
451         }
452
453         if (ioctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
454                 r = NULL;
455                 goto err_allocs;
456         }
457
458         if (!(r = drmMalloc(sizeof(*r))))
459                 return NULL;
460         
461         r->prop_id = prop.prop_id;
462         r->count_values = prop.count_values;
463         
464         r->flags = prop.flags;
465         if (prop.count_values)
466                 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
467         if (prop.flags & DRM_MODE_PROP_ENUM) {
468                 r->count_enums = prop.count_enum_blobs;
469                 r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
470         } else  if (prop.flags & DRM_MODE_PROP_ENUM) {
471                 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
472                 r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
473                 r->count_blobs = prop.count_enum_blobs;
474         }
475         strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
476         r->name[DRM_PROP_NAME_LEN-1] = 0;
477
478 err_allocs:
479         drmFree(U642VOID(prop.values_ptr));
480         drmFree(U642VOID(prop.enum_blob_ptr));
481
482         return r;
483 }
484
485 void drmModeFreeProperty(drmModePropertyPtr ptr)
486 {
487         if (!ptr)
488                 return;
489
490         drmFree(ptr->values);
491         drmFree(ptr->enums);
492         drmFree(ptr);
493 }
494
495 drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
496 {
497         struct drm_mode_get_blob blob;
498         drmModePropertyBlobPtr r;
499
500         blob.length = 0;
501         blob.data = 0;
502         blob.blob_id = blob_id;
503
504         if (ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
505                 return NULL;
506
507         if (blob.length)
508                 blob.data = VOID2U64(drmMalloc(blob.length));
509
510         if (ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
511                 r = NULL;
512                 goto err_allocs;
513         }
514
515         if (!(r = drmMalloc(sizeof(*r))))
516                 return NULL;
517
518         r->id = blob.blob_id;
519         r->length = blob.length;
520         r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
521
522 err_allocs:
523         drmFree(U642VOID(blob.data));
524         return r;
525 }
526
527 void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
528 {
529         if (!ptr)
530                 return;
531
532         drmFree(ptr->data);
533         drmFree(ptr);
534 }
535
536 int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id,
537                              uint64_t value)
538 {
539         struct drm_mode_output_set_property osp;
540         int ret;
541
542         osp.output_id = output_id;
543         osp.prop_id = property_id;
544         osp.value = value;
545
546         if ((ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
547                 return ret;
548
549         return 0;
550 }
551
552 /*
553  * checks if a modesetting capable driver has attached to the pci id
554  * returns 0 if modesetting supported.
555  *  -EINVAL or invalid bus id
556  *  -ENOSYS if no modesetting support
557 */
558 int drmCheckModesettingSupported(const char *busid)
559 {
560 #ifdef __linux__
561         char pci_dev_dir[1024];
562         int domain, bus, dev, func;
563         DIR *sysdir;
564         struct dirent *dent;
565         int found = 0, ret;
566
567         ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
568         if (ret != 4)
569                 return -EINVAL;
570
571         sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
572                 domain, bus, dev, func);
573
574         sysdir = opendir(pci_dev_dir);
575         if (sysdir) {
576                 dent = readdir(sysdir);
577                 while (dent) {
578                         if (!strncmp(dent->d_name, "controlD", 8)) {
579                                 found = 1;
580                                 break;
581                         }
582                 
583                         dent = readdir(sysdir);
584                 }
585                 closedir(sysdir);
586                 if (found)
587                         return 0;
588         }
589
590         sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
591                 domain, bus, dev, func);
592
593         sysdir = opendir(pci_dev_dir);
594         if (!sysdir)
595                 return -EINVAL;
596
597         dent = readdir(sysdir);
598         while (dent) {
599                 if (!strncmp(dent->d_name, "drm:controlD", 12)) {
600                         found = 1;
601                         break;
602                 }
603                 
604                 dent = readdir(sysdir);
605         }
606                         
607         closedir(sysdir);
608         if (found)
609                 return 0;
610 #endif
611         return -ENOSYS;
612
613 }