1 #define LOG_TAG "GRALLOC-ROCKCHIP"
2
3 #include <cutils/log.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <drm.h>
7 #include <rockchip/rockchip_drmif.h>
8
9 #include "gralloc_drm.h"
10 #include "gralloc_drm_priv.h"
11
12 #define UNUSED(...) (void)(__VA_ARGS__)
13
14 struct rockchip_info {
15 struct gralloc_drm_drv_t base;
16
17 struct rockchip_device *rockchip;
18 int fd;
19 };
20
21 struct rockchip_buffer {
22 struct gralloc_drm_bo_t base;
23
24 struct rockchip_bo *bo;
25 };
26
drm_gem_rockchip_destroy(struct gralloc_drm_drv_t * drv)27 static void drm_gem_rockchip_destroy(struct gralloc_drm_drv_t *drv)
28 {
29 struct rockchip_info *info = (struct rockchip_info *)drv;
30
31 if (info->rockchip)
32 rockchip_device_destroy(info->rockchip);
33 free(info);
34 }
35
drm_gem_rockchip_alloc(struct gralloc_drm_drv_t * drv,struct gralloc_drm_handle_t * handle)36 static struct gralloc_drm_bo_t *drm_gem_rockchip_alloc(
37 struct gralloc_drm_drv_t *drv,
38 struct gralloc_drm_handle_t *handle)
39 {
40 struct rockchip_info *info = (struct rockchip_info *)drv;
41 struct rockchip_buffer *buf;
42 struct drm_gem_close args;
43 int ret, cpp, pitch;
44 uint32_t size, gem_handle;
45
46 buf = calloc(1, sizeof(*buf));
47 if (!buf) {
48 ALOGE("Failed to allocate buffer wrapper\n");
49 return NULL;
50 }
51
52 cpp = gralloc_drm_get_bpp(handle->format);
53 if (!cpp) {
54 ALOGE("unrecognized format 0x%x", handle->format);
55 return NULL;
56 }
57
58 gralloc_drm_align_geometry(handle->format,
59 &handle->width, &handle->height);
60
61 /* TODO: We need to sort out alignment */
62 pitch = ALIGN(handle->width * cpp, 64);
63 size = handle->height * pitch;
64
65 if (handle->prime_fd >= 0) {
66 ret = drmPrimeFDToHandle(info->fd, handle->prime_fd,
67 &gem_handle);
68 if (ret) {
69 char *c = NULL;
70 ALOGE("failed to convert prime fd to handle %d ret=%d",
71 handle->prime_fd, ret);
72 *c = 0;
73 goto err;
74 }
75 ALOGV("Got handle %d for fd %d\n", gem_handle, handle->prime_fd);
76
77 buf->bo = rockchip_bo_from_handle(info->rockchip, gem_handle,
78 0, size);
79 if (!buf->bo) {
80 ALOGE("failed to wrap bo handle=%d size=%d\n",
81 gem_handle, size);
82
83 memset(&args, 0, sizeof(args));
84 args.handle = gem_handle;
85 drmIoctl(info->fd, DRM_IOCTL_GEM_CLOSE, &args);
86 return NULL;
87 }
88 } else {
89 buf->bo = rockchip_bo_create(info->rockchip, size, 0);
90 if (!buf->bo) {
91 ALOGE("failed to allocate bo %dx%dx%dx%d\n",
92 handle->height, pitch, cpp, size);
93 goto err;
94 }
95
96 gem_handle = rockchip_bo_handle(buf->bo);
97 ret = drmPrimeHandleToFD(info->fd, gem_handle, 0,
98 &handle->prime_fd);
99 ALOGV("Got fd %d for handle %d\n", handle->prime_fd, gem_handle);
100 if (ret) {
101 ALOGE("failed to get prime fd %d", ret);
102 goto err_unref;
103 }
104
105 buf->base.fb_handle = gem_handle;
106 }
107
108 handle->name = 0;
109 handle->stride = pitch;
110 buf->base.handle = handle;
111
112 return &buf->base;
113
114 err_unref:
115 rockchip_bo_destroy(buf->bo);
116 err:
117 free(buf);
118 return NULL;
119 }
120
drm_gem_rockchip_free(struct gralloc_drm_drv_t * drv,struct gralloc_drm_bo_t * bo)121 static void drm_gem_rockchip_free(struct gralloc_drm_drv_t *drv,
122 struct gralloc_drm_bo_t *bo)
123 {
124 struct rockchip_buffer *buf = (struct rockchip_buffer *)bo;
125
126 UNUSED(drv);
127
128 if (bo->handle && bo->handle->prime_fd)
129 close(bo->handle->prime_fd);
130
131 /* TODO: Is destroy correct here? */
132 rockchip_bo_destroy(buf->bo);
133 free(buf);
134 }
135
drm_gem_rockchip_map(struct gralloc_drm_drv_t * drv,struct gralloc_drm_bo_t * bo,int x,int y,int w,int h,int enable_write,void ** addr)136 static int drm_gem_rockchip_map(struct gralloc_drm_drv_t *drv,
137 struct gralloc_drm_bo_t *bo, int x, int y, int w, int h,
138 int enable_write, void **addr)
139 {
140 struct rockchip_buffer *buf = (struct rockchip_buffer *)bo;
141
142 UNUSED(drv, x, y, w, h, enable_write);
143
144 *addr = rockchip_bo_map(buf->bo);
145 if (!*addr) {
146 ALOGE("failed to map bo\n");
147 return -1;
148 }
149
150 return 0;
151 }
152
drm_gem_rockchip_unmap(struct gralloc_drm_drv_t * drv,struct gralloc_drm_bo_t * bo)153 static void drm_gem_rockchip_unmap(struct gralloc_drm_drv_t *drv,
154 struct gralloc_drm_bo_t *bo)
155 {
156 UNUSED(drv, bo);
157 }
158
gralloc_drm_drv_create_for_rockchip(int fd)159 struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_rockchip(int fd)
160 {
161 struct rockchip_info *info;
162 int ret;
163
164 info = calloc(1, sizeof(*info));
165 if (!info) {
166 ALOGE("Failed to allocate rockchip gralloc device\n");
167 return NULL;
168 }
169
170 info->rockchip = rockchip_device_create(fd);
171 if (!info->rockchip) {
172 ALOGE("Failed to create new rockchip instance\n");
173 free(info);
174 return NULL;
175 }
176
177 info->fd = fd;
178 info->base.destroy = drm_gem_rockchip_destroy;
179 info->base.alloc = drm_gem_rockchip_alloc;
180 info->base.free = drm_gem_rockchip_free;
181 info->base.map = drm_gem_rockchip_map;
182 info->base.unmap = drm_gem_rockchip_unmap;
183
184 return &info->base;
185 }
186