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