Cleaned up userspace interface for modesetting.
[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
40 #include "xf86drmMode.h"
41 #include "xf86drm.h"
42 #include <drm.h>
43 #include <string.h>
44
45 /*
46  * Util functions
47  */
48
49 void* drmAllocCpy(void *array, int count, int entry_size)
50 {
51         char *r;
52         int i;
53
54         if (!count || !array || !entry_size)
55                 return 0;
56
57         if (!(r = drmMalloc(count*entry_size)))
58                 return 0;
59
60         for (i = 0; i < count; i++)
61                 memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
62
63         return r;
64 }
65
66 /**
67  * Generate crtc and output ids.
68  *
69  * Will generate ids starting from 1 up to count if count is greater then 0.
70  */
71 static uint32_t* drmAllocGenerate(int count)
72 {
73         uint32_t *r;
74         int i;
75
76         if(0 <= count)
77                 return 0;
78
79         if (!(r = drmMalloc(count*sizeof(*r))))
80                 return 0;
81
82         for (i = 0; i < count; r[i] = ++i);
83
84         return 0;
85 }
86
87 /*
88  * A couple of free functions.
89  */
90
91 void drmModeFreeModeInfo(struct drm_mode_modeinfo *ptr)
92 {
93         if (!ptr)
94                 return;
95
96         drmFree(ptr);
97 }
98
99 void drmModeFreeResources(drmModeResPtr ptr)
100 {
101         if (!ptr)
102                 return;
103
104         drmFree(ptr->modes);
105         drmFree(ptr);
106
107 }
108
109 void drmModeFreeFB(drmModeFBPtr ptr)
110 {
111         if (!ptr)
112                 return;
113
114         /* we might add more frees later. */
115         drmFree(ptr);
116 }
117
118 void drmModeFreeCrtc(drmModeCrtcPtr ptr)
119 {
120         if (!ptr)
121                 return;
122
123         drmFree(ptr);
124
125 }
126
127 void drmModeFreeOutput(drmModeOutputPtr ptr)
128 {
129         if (!ptr)
130                 return;
131
132         drmFree(ptr->modes);
133         drmFree(ptr);
134
135 }
136
137 /*
138  * ModeSetting functions.
139  */
140
141 drmModeResPtr drmModeGetResources(int fd)
142 {
143         struct drm_mode_card_res res;
144         int i;
145         drmModeResPtr r = 0;
146
147         memset(&res, 0, sizeof(struct drm_mode_card_res));
148
149         if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
150                 return 0;
151
152         if (res.count_fbs)
153                 res.fb_id = drmMalloc(res.count_fbs*sizeof(uint32_t));
154         if (res.count_crtcs)
155                 res.crtc_id = drmMalloc(res.count_crtcs*sizeof(uint32_t));
156         if (res.count_outputs)
157                 res.output_id = drmMalloc(res.count_outputs*sizeof(uint32_t));
158         if (res.count_modes)
159                 res.modes = drmMalloc(res.count_modes*sizeof(*res.modes));
160
161         if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
162                 r = NULL;
163                 goto err_allocs;
164         }
165
166         /*
167          * return
168          */
169
170
171         if (!(r = drmMalloc(sizeof(*r))))
172                 return 0;
173
174         r->count_fbs     = res.count_fbs;
175         r->count_crtcs   = res.count_crtcs;
176         r->count_outputs = res.count_outputs;
177         r->count_modes   = res.count_modes;
178         /* TODO we realy should test if these allocs fails. */
179         r->fbs           = drmAllocCpy(res.fb_id, res.count_fbs, sizeof(uint32_t));
180         r->crtcs         = drmAllocCpy(res.crtc_id, res.count_crtcs, sizeof(uint32_t));
181         r->outputs       = drmAllocCpy(res.output_id, res.count_outputs, sizeof(uint32_t));
182         r->modes         = drmAllocCpy(res.modes, res.count_modes, sizeof(struct drm_mode_modeinfo));
183
184 err_allocs:
185         drmFree(res.fb_id);
186         drmFree(res.crtc_id);
187         drmFree(res.output_id);
188         drmFree(res.modes);
189
190         return r;
191 }
192
193 int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
194                  uint8_t bpp, uint32_t pitch, drmBO *bo, uint32_t *buf_id)
195 {
196         struct drm_mode_fb_cmd f;
197         int ret;
198
199         f.width  = width;
200         f.height = height;
201         f.pitch  = pitch;
202         f.bpp    = bpp;
203         f.depth  = depth;
204         f.handle = bo->handle;
205
206         if (ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f))
207                 return ret;
208
209         *buf_id = f.buffer_id;
210         return 0;
211 }
212
213 int drmModeRmFB(int fd, uint32_t bufferId)
214 {
215         return ioctl(fd, DRM_IOCTL_MODE_RMFB, bufferId);
216 }
217
218 drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
219 {
220         struct drm_mode_fb_cmd info;
221         drmModeFBPtr r;
222
223         info.buffer_id = buf;
224
225         if (ioctl(fd, DRM_IOCTL_MODE_GETFB, &info))
226                 return NULL;
227
228         if (!(r = drmMalloc(sizeof(*r))))
229                 return NULL;
230
231         r->buffer_id = info.buffer_id;
232         r->width = info.width;
233         r->height = info.height;
234         r->pitch = info.pitch;
235         r->bpp = info.bpp;
236         r->handle = info.handle;
237         r->depth = info.depth;
238
239         return r;
240 }
241
242
243 /*
244  * Crtc functions
245  */
246
247 drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
248 {
249         struct drm_mode_crtc crtc;
250         drmModeCrtcPtr r;
251         int i = 0;
252
253         crtc.count_outputs   = 0;
254         crtc.outputs         = 0;
255         crtc.count_possibles = 0;
256         crtc.possibles       = 0;
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->x               = crtc.x;
270         r->y               = crtc.y;
271         r->mode            = crtc.mode;
272         r->buffer_id       = crtc.fb_id;
273         r->gamma_size      = crtc.gamma_size;
274         r->count_outputs   = crtc.count_outputs;
275         r->count_possibles = crtc.count_possibles;
276         /* TODO we realy should test if these alloc & cpy fails. */
277         r->outputs         = crtc.outputs;
278         r->possibles       = crtc.possibles;
279
280         return r;
281
282 err_allocs:
283
284         return 0;
285 }
286
287
288 int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
289                    uint32_t x, uint32_t y, uint32_t modeId,
290                    uint32_t *outputs, int count)
291 {
292         struct drm_mode_crtc crtc;
293
294         crtc.count_outputs   = 0;
295         crtc.outputs         = 0;
296         crtc.count_possibles = 0;
297         crtc.possibles       = 0;
298
299         crtc.x             = x;
300         crtc.y             = y;
301         crtc.crtc_id       = crtcId;
302         crtc.fb_id         = bufferId;
303         crtc.set_outputs   = outputs;
304         crtc.count_outputs = count;
305         crtc.mode          = modeId;
306
307         return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
308 }
309
310
311 /*
312  * Output manipulation
313  */
314
315 drmModeOutputPtr drmModeGetOutput(int fd, uint32_t output_id)
316 {
317         struct drm_mode_get_output out;
318         drmModeOutputPtr r = 0;
319
320         out.output = output_id;
321         out.count_crtcs  = 0;
322         out.crtcs        = 0;
323         out.count_clones = 0;
324         out.clones       = 0;
325         out.count_modes  = 0;
326         out.modes        = 0;
327
328         if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
329                 return 0;
330
331         if (out.count_modes)
332                 out.modes = drmMalloc(out.count_modes*sizeof(uint32_t));
333
334         if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
335                 goto err_allocs;
336
337         if(!(r = drmMalloc(sizeof(*r))))
338                 return 0;
339
340         r->connection   = out.connection;
341         r->mmWidth      = out.mm_width;
342         r->mmHeight     = out.mm_height;
343         r->subpixel     = out.subpixel;
344         r->count_crtcs  = out.count_crtcs;
345         r->count_clones = out.count_clones;
346         r->count_modes  = out.count_modes;
347         /* TODO we should test if these alloc & cpy fails. */
348         r->crtcs        = out.crtcs;
349         r->clones       = out.clones;
350         r->modes        = drmAllocCpy(out.modes, out.count_modes, sizeof(uint32_t));
351         strncpy(r->name, out.name, DRM_OUTPUT_NAME_LEN);
352         r->name[DRM_OUTPUT_NAME_LEN-1] = 0;
353         return r;
354
355 err_allocs:
356         drmFree(out.modes);
357
358         return 0;
359 }
360
361 uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *mode_info)
362 {
363         if (ioctl(fd, DRM_IOCTL_MODE_ADDMODE, mode_info))
364                 return 0;
365         
366         return mode_info->id;
367 }
368
369 int drmModeRmMode(int fd, uint32_t mode_id)
370 {
371         return ioctl(fd, DRM_IOCTL_MODE_RMMODE, mode_id);
372 }
373
374 int drmModeAttachMode(int fd, uint32_t output_id, uint32_t mode_id)
375 {
376
377         struct drm_mode_mode_cmd res;
378
379         res.output_id = output_id;
380         res.mode_id = mode_id;
381
382         return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
383 }
384
385 int drmModeDetachMode(int fd, uint32_t output_id, uint32_t mode_id)
386 {
387         struct drm_mode_mode_cmd res;
388
389         res.output_id = output_id;
390         res.mode_id = mode_id;
391
392         return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
393 }
394
395