mode: Minor reodering and renaming
[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 drmModeFreeConnector(drmModeConnectorPtr ptr)
113 {
114         if (!ptr)
115                 return;
116
117         drmFree(ptr->modes);
118         drmFree(ptr);
119
120 }
121
122 void drmModeFreeEncoder(drmModeEncoderPtr ptr)
123 {
124         drmFree(ptr);
125 }
126
127 /*
128  * ModeSetting functions.
129  */
130
131 drmModeResPtr drmModeGetResources(int fd)
132 {
133         struct drm_mode_card_res res;
134         drmModeResPtr r = 0;
135
136         memset(&res, 0, sizeof(struct drm_mode_card_res));
137
138         if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
139                 return 0;
140
141         if (res.count_fbs)
142                 res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
143         if (res.count_crtcs)
144                 res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
145         if (res.count_connectors)
146                 res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
147         if (res.count_encoders)
148                 res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
149
150         if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
151                 r = NULL;
152                 goto err_allocs;
153         }
154
155         /*
156          * return
157          */
158
159
160         if (!(r = drmMalloc(sizeof(*r))))
161                 return 0;
162
163         r->min_width     = res.min_width;
164         r->max_width     = res.max_width;
165         r->min_height    = res.min_height;
166         r->max_height    = res.max_height;
167         r->count_fbs     = res.count_fbs;
168         r->count_crtcs   = res.count_crtcs;
169         r->count_connectors = res.count_connectors;
170         r->count_encoders = res.count_encoders;
171         /* TODO we realy should test if these allocs fails. */
172         r->fbs           = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
173         r->crtcs         = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
174         r->connectors       = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
175         r->encoders      = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
176
177 err_allocs:
178         drmFree(U642VOID(res.fb_id_ptr));
179         drmFree(U642VOID(res.crtc_id_ptr));
180         drmFree(U642VOID(res.connector_id_ptr));
181         drmFree(U642VOID(res.encoder_id_ptr));
182
183         return r;
184 }
185
186 int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
187                  uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
188                  uint32_t *buf_id)
189 {
190         struct drm_mode_fb_cmd f;
191         int ret;
192
193         f.width  = width;
194         f.height = height;
195         f.pitch  = pitch;
196         f.bpp    = bpp;
197         f.depth  = depth;
198         f.handle = bo_handle;
199
200         if ((ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
201                 return ret;
202
203         *buf_id = f.fb_id;
204         return 0;
205 }
206
207 int drmModeRmFB(int fd, uint32_t bufferId)
208 {
209         return ioctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
210
211
212 }
213
214 drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
215 {
216         struct drm_mode_fb_cmd info;
217         drmModeFBPtr r;
218
219         info.fb_id = buf;
220
221         if (ioctl(fd, DRM_IOCTL_MODE_GETFB, &info))
222                 return NULL;
223
224         if (!(r = drmMalloc(sizeof(*r))))
225                 return NULL;
226
227         r->fb_id = info.fb_id;
228         r->width = info.width;
229         r->height = info.height;
230         r->pitch = info.pitch;
231         r->bpp = info.bpp;
232         r->handle = info.handle;
233         r->depth = info.depth;
234
235         return r;
236 }
237
238
239 /*
240  * Crtc functions
241  */
242
243 drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
244 {
245         struct drm_mode_crtc crtc;
246         drmModeCrtcPtr r;
247
248         crtc.crtc_id = crtcId;
249
250         if (ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
251                 return 0;
252
253         /*
254          * return
255          */
256
257         if (!(r = drmMalloc(sizeof(*r))))
258                 return 0;
259         
260         r->crtc_id         = crtc.crtc_id;
261         r->x               = crtc.x;
262         r->y               = crtc.y;
263         r->mode_valid      = crtc.mode_valid;
264         if (r->mode_valid)
265                 memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
266         r->buffer_id       = crtc.fb_id;
267         r->gamma_size      = crtc.gamma_size;
268         return r;
269 }
270
271
272 int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
273                    uint32_t x, uint32_t y, uint32_t *connectors, int count,
274                    struct drm_mode_modeinfo *mode)
275 {
276         struct drm_mode_crtc crtc;
277
278         crtc.x             = x;
279         crtc.y             = y;
280         crtc.crtc_id       = crtcId;
281         crtc.fb_id         = bufferId;
282         crtc.set_connectors_ptr = VOID2U64(connectors);
283         crtc.count_connectors = count;
284         if (mode) {
285           memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
286           crtc.mode_valid = 1;
287         } else
288           crtc.mode_valid = 0;
289
290         return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
291 }
292
293 /*
294  * Cursor manipulation
295  */
296
297 int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
298 {
299         struct drm_mode_cursor arg;
300
301         arg.flags = DRM_MODE_CURSOR_BO;
302         arg.crtc_id = crtcId;
303         arg.width = width;
304         arg.height = height;
305         arg.handle = bo_handle;
306
307         return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
308 }
309
310 int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
311 {
312         struct drm_mode_cursor arg;
313
314         arg.flags = DRM_MODE_CURSOR_MOVE;
315         arg.crtc_id = crtcId;
316         arg.x = x;
317         arg.y = y;
318
319         return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
320 }
321
322 /*
323  * Encoder get 
324  */
325 drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
326 {
327         struct drm_mode_get_encoder enc;
328         drmModeEncoderPtr r = NULL;
329
330         enc.encoder_id = encoder_id;
331         enc.encoder_type = 0;
332         enc.possible_crtcs = 0;
333         enc.possible_clones = 0;
334
335         if (ioctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
336                 return 0;
337
338         if (!(r = drmMalloc(sizeof(*r))))
339                 return 0;
340
341         r->encoder_id = enc.encoder_id;
342         r->crtc_id = enc.crtc_id;
343         r->encoder_type = enc.encoder_type;
344         r->possible_crtcs = enc.possible_crtcs;
345         r->possible_clones = enc.possible_clones;
346
347         return r;
348 }
349
350 /*
351  * Connector manipulation
352  */
353
354 drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
355 {
356         struct drm_mode_get_connector conn;
357         drmModeConnectorPtr r = NULL;
358
359         conn.connector_id = connector_id;
360         conn.connector_type_id = 0;
361         conn.connector_type  = 0;
362         conn.count_modes  = 0;
363         conn.modes_ptr    = 0;
364         conn.count_props  = 0;
365         conn.props_ptr    = 0;
366         conn.prop_values_ptr = 0;
367         conn.count_encoders  = 0;
368         conn.encoders_ptr = 0;
369
370         if (ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
371                 return 0;
372
373         if (conn.count_props) {
374                 conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
375                 conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
376         }
377
378         if (conn.count_modes)
379                 conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
380
381         if (conn.count_encoders)
382                 conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
383
384         if (ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
385                 goto err_allocs;
386
387         if(!(r = drmMalloc(sizeof(*r)))) {
388                 goto err_allocs;
389         }
390
391         r->connector_id = conn.connector_id;
392         r->encoder_id = conn.encoder_id;
393         r->connection   = conn.connection;
394         r->mmWidth      = conn.mm_width;
395         r->mmHeight     = conn.mm_height;
396         r->subpixel     = conn.subpixel;
397         r->count_modes  = conn.count_modes;
398         /* TODO we should test if these alloc & cpy fails. */
399         r->count_props  = conn.count_props;
400         r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
401         r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
402         r->modes        = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
403         r->count_encoders = conn.count_encoders;
404         r->encoders     = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
405         r->connector_type  = conn.connector_type;
406         r->connector_type_id = conn.connector_type_id;
407
408         if (!r->props || !r->prop_values || !r->modes || !r->encoders)
409                 goto err_allocs;
410
411 err_allocs:
412         drmFree(U642VOID(conn.prop_values_ptr));
413         drmFree(U642VOID(conn.props_ptr));
414         drmFree(U642VOID(conn.modes_ptr));
415         drmFree(U642VOID(conn.encoders_ptr));
416
417         return r;
418 }
419
420 int drmModeAttachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
421 {
422         struct drm_mode_mode_cmd res;
423
424         memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
425         res.connector_id = connector_id;
426
427         return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
428 }
429
430 int drmModeDetachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
431 {
432         struct drm_mode_mode_cmd res;
433
434         memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
435         res.connector_id = connector_id;
436
437         return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
438 }
439
440
441 drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
442 {
443         struct drm_mode_get_property prop;
444         drmModePropertyPtr r;
445
446         prop.prop_id = property_id;
447         prop.count_enum_blobs = 0;
448         prop.count_values = 0;
449         prop.flags = 0;
450         prop.enum_blob_ptr = 0;
451         prop.values_ptr = 0;
452
453         if (ioctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
454                 return 0;
455
456         if (prop.count_values)
457                 prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
458
459         if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
460                 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
461
462         if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
463                 prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
464                 prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
465         }
466
467         if (ioctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
468                 r = NULL;
469                 goto err_allocs;
470         }
471
472         if (!(r = drmMalloc(sizeof(*r))))
473                 return NULL;
474         
475         r->prop_id = prop.prop_id;
476         r->count_values = prop.count_values;
477         
478         r->flags = prop.flags;
479         if (prop.count_values)
480                 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
481         if (prop.flags & DRM_MODE_PROP_ENUM) {
482                 r->count_enums = prop.count_enum_blobs;
483                 r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
484         } else if (prop.flags & DRM_MODE_PROP_BLOB) {
485                 r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
486                 r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
487                 r->count_blobs = prop.count_enum_blobs;
488         }
489         strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
490         r->name[DRM_PROP_NAME_LEN-1] = 0;
491
492 err_allocs:
493         drmFree(U642VOID(prop.values_ptr));
494         drmFree(U642VOID(prop.enum_blob_ptr));
495
496         return r;
497 }
498
499 void drmModeFreeProperty(drmModePropertyPtr ptr)
500 {
501         if (!ptr)
502                 return;
503
504         drmFree(ptr->values);
505         drmFree(ptr->enums);
506         drmFree(ptr);
507 }
508
509 drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
510 {
511         struct drm_mode_get_blob blob;
512         drmModePropertyBlobPtr r;
513
514         blob.length = 0;
515         blob.data = 0;
516         blob.blob_id = blob_id;
517
518         if (ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
519                 return NULL;
520
521         if (blob.length)
522                 blob.data = VOID2U64(drmMalloc(blob.length));
523
524         if (ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
525                 r = NULL;
526                 goto err_allocs;
527         }
528
529         if (!(r = drmMalloc(sizeof(*r))))
530                 return NULL;
531
532         r->id = blob.blob_id;
533         r->length = blob.length;
534         r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
535
536 err_allocs:
537         drmFree(U642VOID(blob.data));
538         return r;
539 }
540
541 void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
542 {
543         if (!ptr)
544                 return;
545
546         drmFree(ptr->data);
547         drmFree(ptr);
548 }
549
550 int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
551                              uint64_t value)
552 {
553         struct drm_mode_connector_set_property osp;
554         int ret;
555
556         osp.connector_id = connector_id;
557         osp.prop_id = property_id;
558         osp.value = value;
559
560         if ((ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
561                 return ret;
562
563         return 0;
564 }
565
566 /*
567  * checks if a modesetting capable driver has attached to the pci id
568  * returns 0 if modesetting supported.
569  *  -EINVAL or invalid bus id
570  *  -ENOSYS if no modesetting support
571 */
572 int drmCheckModesettingSupported(const char *busid)
573 {
574 #ifdef __linux__
575         char pci_dev_dir[1024];
576         int domain, bus, dev, func;
577         DIR *sysdir;
578         struct dirent *dent;
579         int found = 0, ret;
580
581         ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
582         if (ret != 4)
583                 return -EINVAL;
584
585         sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
586                 domain, bus, dev, func);
587
588         sysdir = opendir(pci_dev_dir);
589         if (sysdir) {
590                 dent = readdir(sysdir);
591                 while (dent) {
592                         if (!strncmp(dent->d_name, "controlD", 8)) {
593                                 found = 1;
594                                 break;
595                         }
596                 
597                         dent = readdir(sysdir);
598                 }
599                 closedir(sysdir);
600                 if (found)
601                         return 0;
602         }
603
604         sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
605                 domain, bus, dev, func);
606
607         sysdir = opendir(pci_dev_dir);
608         if (!sysdir)
609                 return -EINVAL;
610
611         dent = readdir(sysdir);
612         while (dent) {
613                 if (!strncmp(dent->d_name, "drm:controlD", 12)) {
614                         found = 1;
615                         break;
616                 }
617                 
618                 dent = readdir(sysdir);
619         }
620                         
621         closedir(sysdir);
622         if (found)
623                 return 0;
624 #endif
625         return -ENOSYS;
626
627 }
628
629 int drmModeReplaceFB(int fd, uint32_t buffer_id,
630                      uint32_t width, uint32_t height, uint8_t depth,
631                      uint8_t bpp, uint32_t pitch, uint32_t bo_handle)
632 {
633         struct drm_mode_fb_cmd f;
634         int ret;
635
636         f.width = width;
637         f.height = height;
638         f.pitch = pitch;
639         f.bpp = bpp;
640         f.depth = depth;
641         f.handle = bo_handle;
642         f.fb_id = buffer_id;
643
644         if ((ret = ioctl(fd, DRM_IOCTL_MODE_REPLACEFB, &f)))
645                 return ret;
646
647         return 0;
648 }
649
650 int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
651                         uint16_t *red, uint16_t *green, uint16_t *blue)
652 {
653         int ret;
654         struct drm_mode_crtc_lut l;
655
656         l.crtc_id = crtc_id;
657         l.gamma_size = size;
658         l.red = VOID2U64(red);
659         l.green = VOID2U64(green);
660         l.blue = VOID2U64(blue);
661         
662         if ((ret = ioctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l)))
663                 return ret;
664
665         return 0;
666 }
667
668 int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
669                         uint16_t *red, uint16_t *green, uint16_t *blue)
670 {
671         int ret;
672         struct drm_mode_crtc_lut l;
673
674         l.crtc_id = crtc_id;
675         l.gamma_size = size;
676         l.red = VOID2U64(red);
677         l.green = VOID2U64(green);
678         l.blue = VOID2U64(blue);
679         
680         if ((ret = ioctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l)))
681                 return ret;
682
683         return 0;
684 }