libkms: remove explicit define _FILE_OFFSET_BITS 64
[platform/upstream/libdrm.git] / libkms / exynos.c
1 /* exynos.c
2  *
3  * Copyright 2009 Samsung Electronics Co., Ltd.
4  * Authors:
5  *      SooChan Lim <sc1.lim@samsung.com>
6  *      Sangjin LEE <lsj119@samsung.com>
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "internal.h"
23
24 #include <sys/mman.h>
25 #include <sys/ioctl.h>
26 #include "xf86drm.h"
27
28 #include "exynos_drm.h"
29
30 struct exynos_bo
31 {
32         struct kms_bo base;
33         unsigned map_count;
34 };
35
36 static int
37 exynos_get_prop(struct kms_driver *kms, unsigned key, unsigned *out)
38 {
39         switch (key) {
40         case KMS_BO_TYPE:
41                 *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 | KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
42                 break;
43         default:
44                 return -EINVAL;
45         }
46         return 0;
47 }
48
49 static int
50 exynos_destroy(struct kms_driver *kms)
51 {
52         free(kms);
53         return 0;
54 }
55
56 static int
57 exynos_bo_create(struct kms_driver *kms,
58                  const unsigned width, const unsigned height,
59                  const enum kms_bo_type type, const unsigned *attr,
60                  struct kms_bo **out)
61 {
62         struct drm_exynos_gem_create arg;
63         unsigned size, pitch;
64         struct exynos_bo *bo;
65         int i, ret;
66
67         for (i = 0; attr[i]; i += 2) {
68                 switch (attr[i]) {
69                 case KMS_WIDTH:
70                 case KMS_HEIGHT:
71                 case KMS_BO_TYPE:
72                         break;
73                 default:
74                         return -EINVAL;
75                 }
76         }
77
78         bo = calloc(1, sizeof(*bo));
79         if (!bo)
80                 return -ENOMEM;
81
82         if (type == KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8) {
83                 pitch = 64 * 4;
84                 size = 64 * 64 * 4;
85         } else if (type == KMS_BO_TYPE_SCANOUT_X8R8G8B8) {
86                 pitch = width * 4;
87                 pitch = (pitch + 512 - 1) & ~(512 - 1);
88                 size = pitch * ((height + 4 - 1) & ~(4 - 1));
89         } else {
90                 return -EINVAL;
91         }
92
93         memset(&arg, 0, sizeof(arg));
94         arg.size = size;
95
96         ret = drmCommandWriteRead(kms->fd, DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg));
97         if (ret)
98                 goto err_free;
99
100         bo->base.kms = kms;
101         bo->base.handle = arg.handle;
102         bo->base.size = size;
103         bo->base.pitch = pitch;
104
105         *out = &bo->base;
106
107         return 0;
108
109 err_free:
110         free(bo);
111         return ret;
112 }
113
114 static int
115 exynos_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out)
116 {
117         switch (key) {
118         default:
119                 return -EINVAL;
120         }
121 }
122
123 static int
124 exynos_bo_map(struct kms_bo *_bo, void **out)
125 {
126         struct exynos_bo *bo = (struct exynos_bo *)_bo;
127         struct drm_exynos_gem_map_off arg;
128         void *map = NULL;
129         int ret;
130
131         if (bo->base.ptr) {
132                 bo->map_count++;
133                 *out = bo->base.ptr;
134                 return 0;
135         }
136
137         memset(&arg, 0, sizeof(arg));
138         arg.handle = bo->base.handle;
139
140         ret = drmCommandWriteRead(bo->base.kms->fd, DRM_EXYNOS_GEM_MAP_OFFSET, &arg, sizeof(arg));
141         if (ret)
142                 return ret;
143
144         map = mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->base.kms->fd, arg.offset);
145         if (map == MAP_FAILED)
146                 return -errno;
147
148         bo->base.ptr = map;
149         bo->map_count++;
150         *out = bo->base.ptr;
151
152         return 0;
153 }
154
155 static int
156 exynos_bo_unmap(struct kms_bo *_bo)
157 {
158         struct exynos_bo *bo = (struct exynos_bo *)_bo;
159         bo->map_count--;
160         return 0;
161 }
162
163 static int
164 exynos_bo_destroy(struct kms_bo *_bo)
165 {
166         struct exynos_bo *bo = (struct exynos_bo *)_bo;
167         struct drm_gem_close arg;
168         int ret;
169
170         if (bo->base.ptr) {
171                 /* XXX Sanity check map_count */
172                 munmap(bo->base.ptr, bo->base.size);
173                 bo->base.ptr = NULL;
174         }
175
176         memset(&arg, 0, sizeof(arg));
177         arg.handle = bo->base.handle;
178
179         ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_GEM_CLOSE, &arg);
180         if (ret)
181                 return -errno;
182
183         free(bo);
184         return 0;
185 }
186
187 int
188 exynos_create(int fd, struct kms_driver **out)
189 {
190         struct kms_driver *kms;
191
192         kms = calloc(1, sizeof(*kms));
193         if (!kms)
194                 return -ENOMEM;
195
196         kms->fd = fd;
197
198         kms->bo_create = exynos_bo_create;
199         kms->bo_map = exynos_bo_map;
200         kms->bo_unmap = exynos_bo_unmap;
201         kms->bo_get_prop = exynos_bo_get_prop;
202         kms->bo_destroy = exynos_bo_destroy;
203         kms->get_prop = exynos_get_prop;
204         kms->destroy = exynos_destroy;
205         *out = kms;
206
207         return 0;
208 }