OSDN Git Service

93e36a12ef27c5907e141c363b9c3725e0ff0789
[android-x86/external-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 #define HAVE_STDINT_H
15 #define _FILE_OFFSET_BITS 64
16
17 #include <errno.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "internal.h"
22
23 #include <sys/mman.h>
24 #include <sys/ioctl.h>
25 #include "xf86drm.h"
26
27 #include "exynos_drm.h"
28
29 struct exynos_bo
30 {
31         struct kms_bo base;
32         unsigned map_count;
33 };
34
35 static int
36 exynos_get_prop(struct kms_driver *kms, unsigned key, unsigned *out)
37 {
38         switch (key) {
39         case KMS_BO_TYPE:
40                 *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 | KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
41                 break;
42         default:
43                 return -EINVAL;
44         }
45         return 0;
46 }
47
48 static int
49 exynos_destroy(struct kms_driver *kms)
50 {
51         free(kms);
52         return 0;
53 }
54
55 static int
56 exynos_bo_create(struct kms_driver *kms,
57                  const unsigned width, const unsigned height,
58                  const enum kms_bo_type type, const unsigned *attr,
59                  struct kms_bo **out)
60 {
61         struct drm_exynos_gem_create arg;
62         unsigned size, pitch;
63         struct exynos_bo *bo;
64         int i, ret;
65
66         for (i = 0; attr[i]; i += 2) {
67                 switch (attr[i]) {
68                 case KMS_WIDTH:
69                 case KMS_HEIGHT:
70                 case KMS_BO_TYPE:
71                         break;
72                 default:
73                         return -EINVAL;
74                 }
75         }
76
77         bo = calloc(1, sizeof(*bo));
78         if (!bo)
79                 return -ENOMEM;
80
81         if (type == KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8) {
82                 pitch = 64 * 4;
83                 size = 64 * 64 * 4;
84         } else if (type == KMS_BO_TYPE_SCANOUT_X8R8G8B8) {
85                 pitch = width * 4;
86                 pitch = (pitch + 512 - 1) & ~(512 - 1);
87                 size = pitch * ((height + 4 - 1) & ~(4 - 1));
88         } else {
89                 return -EINVAL;
90         }
91
92         memset(&arg, 0, sizeof(arg));
93         arg.size = size;
94
95         ret = drmCommandWriteRead(kms->fd, DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg));
96         if (ret)
97                 goto err_free;
98
99         bo->base.kms = kms;
100         bo->base.handle = arg.handle;
101         bo->base.size = size;
102         bo->base.pitch = pitch;
103
104         *out = &bo->base;
105
106         return 0;
107
108 err_free:
109         free(bo);
110         return ret;
111 }
112
113 static int
114 exynos_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out)
115 {
116         switch (key) {
117         default:
118                 return -EINVAL;
119         }
120 }
121
122 static int
123 exynos_bo_map(struct kms_bo *_bo, void **out)
124 {
125         struct exynos_bo *bo = (struct exynos_bo *)_bo;
126         struct drm_exynos_gem_map_off arg;
127         void *map = NULL;
128         int ret;
129
130         if (bo->base.ptr) {
131                 bo->map_count++;
132                 *out = bo->base.ptr;
133                 return 0;
134         }
135
136         memset(&arg, 0, sizeof(arg));
137         arg.handle = bo->base.handle;
138
139         ret = drmCommandWriteRead(bo->base.kms->fd, DRM_EXYNOS_GEM_MAP_OFFSET, &arg, sizeof(arg));
140         if (ret)
141                 return ret;
142
143         map = mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->base.kms->fd, arg.offset);
144         if (map == MAP_FAILED)
145                 return -errno;
146
147         bo->base.ptr = map;
148         bo->map_count++;
149         *out = bo->base.ptr;
150
151         return 0;
152 }
153
154 static int
155 exynos_bo_unmap(struct kms_bo *_bo)
156 {
157         struct exynos_bo *bo = (struct exynos_bo *)_bo;
158         bo->map_count--;
159         return 0;
160 }
161
162 static int
163 exynos_bo_destroy(struct kms_bo *_bo)
164 {
165         struct exynos_bo *bo = (struct exynos_bo *)_bo;
166         struct drm_gem_close arg;
167         int ret;
168
169         if (bo->base.ptr) {
170                 /* XXX Sanity check map_count */
171                 munmap(bo->base.ptr, bo->base.size);
172                 bo->base.ptr = NULL;
173         }
174
175         memset(&arg, 0, sizeof(arg));
176         arg.handle = bo->base.handle;
177
178         ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_GEM_CLOSE, &arg);
179         if (ret)
180                 return -errno;
181
182         free(bo);
183         return 0;
184 }
185
186 int
187 exynos_create(int fd, struct kms_driver **out)
188 {
189         struct kms_driver *kms;
190
191         kms = calloc(1, sizeof(*kms));
192         if (!kms)
193                 return -ENOMEM;
194
195         kms->fd = fd;
196
197         kms->bo_create = exynos_bo_create;
198         kms->bo_map = exynos_bo_map;
199         kms->bo_unmap = exynos_bo_unmap;
200         kms->bo_get_prop = exynos_bo_get_prop;
201         kms->bo_destroy = exynos_bo_destroy;
202         kms->get_prop = exynos_get_prop;
203         kms->destroy = exynos_destroy;
204         *out = kms;
205
206         return 0;
207 }