Add support for user defined modes
[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
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 #if 0
242 int drmModeForceProbe(int fd, uint32_t outputId)
243 {
244         /* TODO impl/keep? */
245 }
246
247 #endif
248 /*
249  * Crtc function.
250  */
251
252 drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
253 {
254         struct drm_mode_crtc crtc;
255         drmModeCrtcPtr r;
256         int i = 0;
257
258         crtc.count_outputs   = 0;
259         crtc.outputs         = 0;
260         crtc.count_possibles = 0;
261         crtc.possibles       = 0;
262         crtc.crtc_id = crtcId;
263
264         if (ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
265                 return 0;
266
267         /*
268          * return
269          */
270
271         if (!(r = drmMalloc(sizeof(*r))))
272                 return 0;
273
274         r->x               = crtc.x;
275         r->y               = crtc.y;
276         r->mode            = crtc.mode;
277 //      r->width           = crtc.width;
278 //      r->height          = crtc.height;
279         r->buffer_id        = crtc.fb_id;
280         r->gamma_size      = crtc.gamma_size;
281         r->count_outputs   = crtc.count_outputs;
282         r->count_possibles = crtc.count_possibles;
283         /* TODO we realy should test if these alloc & cpy fails. */
284         r->outputs         = crtc.outputs;
285         r->possibles       = crtc.possibles;
286
287         return r;
288
289 err_allocs:
290
291         return 0;
292 }
293
294
295 int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
296                    uint32_t x, uint32_t y, uint32_t modeId,
297                    uint32_t *outputs, int count)
298 {
299         struct drm_mode_crtc crtc;
300
301         crtc.count_outputs   = 0;
302         crtc.outputs         = 0;
303         crtc.count_possibles = 0;
304         crtc.possibles       = 0;
305
306         crtc.x             = x;
307         crtc.y             = y;
308         crtc.crtc_id        = crtcId;
309         crtc.fb_id      = bufferId;
310         crtc.set_outputs   = outputs;
311         crtc.count_outputs = count;
312         crtc.mode          = modeId;
313
314         return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
315 }
316
317 #if 0
318 drmModeGammaTriplePtr drmModeGetCrtcGamma(int fd, uint32_t crtc, int *count)
319 {
320         /* TODO impl */
321 }
322
323 int drmModeSetCrtcGamma(int fd, uint32_t crtcId,
324                 drmModeGammaTriplePtr ptr, int count)
325 {
326         /* TODO impl */
327 }
328
329 #endif
330 /*
331  * Output manipulation
332  */
333 drmModeOutputPtr drmModeGetOutput(int fd, uint32_t output_id)
334 {
335         struct drm_mode_get_output out;
336         drmModeOutputPtr r = 0;
337
338         out.output = output_id;
339         out.count_crtcs  = 0;
340         out.crtcs        = 0;
341         out.count_clones = 0;
342         out.clones       = 0;
343         out.count_modes  = 0;
344         out.modes        = 0;
345
346         if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
347                 return 0;
348
349         if (out.count_modes)
350                 out.modes = drmMalloc(out.count_modes*sizeof(uint32_t));
351
352         if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
353                 goto err_allocs;
354
355         if(!(r = drmMalloc(sizeof(*r))))
356                 return 0;
357
358         r->connection   = out.connection;
359         r->mmWidth      = out.mm_width;
360         r->mmHeight     = out.mm_height;
361         r->subpixel     = out.subpixel;
362         r->count_crtcs  = out.count_crtcs;
363         r->count_clones = out.count_clones;
364         r->count_modes  = out.count_modes;
365         /* TODO we should test if these alloc & cpy fails. */
366         r->crtcs        = out.crtcs;
367         r->clones       = out.clones;
368         r->modes        = drmAllocCpy(out.modes, out.count_modes, sizeof(uint32_t));
369         strncpy(r->name, out.name, DRM_OUTPUT_NAME_LEN);
370         r->name[DRM_OUTPUT_NAME_LEN-1] = 0;
371         return r;
372
373 err_allocs:
374         drmFree(out.modes);
375
376         return 0;
377 }
378
379 uint32_t drmModeAddMode(int fd, struct drm_mode_modeinfo *mode_info)
380 {
381         if (ioctl(fd, DRM_IOCTL_MODE_ADDMODE, mode_info))
382                 return 0;
383         
384         return mode_info->id;
385 }
386
387 int drmModeRmMode(int fd, uint32_t mode_id)
388 {
389         return ioctl(fd, DRM_IOCTL_MODE_RMMODE, mode_id);
390 }
391
392 int drmModeAttachMode(int fd, uint32_t output_id, uint32_t mode_id)
393 {
394
395         struct drm_mode_mode_cmd res;
396
397         res.output_id = output_id;
398         res.mode_id = mode_id;
399
400         return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
401 }
402
403 int drmModeDetachMode(int fd, uint32_t output_id, uint32_t mode_id)
404 {
405         struct drm_mode_mode_cmd res;
406
407         res.output_id = output_id;
408         res.mode_id = mode_id;
409
410         return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
411 }
412
413