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