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, aligned_width, aligned_height;
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 aligned_width = handle->width;
59 aligned_height = handle->height;
60 gralloc_drm_align_geometry(handle->format,
61 &aligned_width, &aligned_height);
62
63 /* TODO: We need to sort out alignment */
64 pitch = ALIGN(aligned_width * cpp, 64);
65 size = aligned_height * pitch;
66
67 if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
68 /*
69 * WAR for H264 decoder requiring additional space
70 * at the end of destination buffers.
71 */
72 uint32_t w_mbs, h_mbs;
73
74 w_mbs = ALIGN(handle->width, 16) / 16;
75 h_mbs = ALIGN(handle->height, 16) / 16;
76 size += 64 * w_mbs * h_mbs;
77 }
78
79 if (handle->prime_fd >= 0) {
80 ret = drmPrimeFDToHandle(info->fd, handle->prime_fd,
81 &gem_handle);
82 if (ret) {
83 char *c = NULL;
84 ALOGE("failed to convert prime fd to handle %d ret=%d",
85 handle->prime_fd, ret);
86 *c = 0;
87 goto err;
88 }
89 ALOGV("Got handle %d for fd %d\n", gem_handle, handle->prime_fd);
90
91 buf->bo = rockchip_bo_from_handle(info->rockchip, gem_handle,
92 0, size);
93 if (!buf->bo) {
94 ALOGE("failed to wrap bo handle=%d size=%d\n",
95 gem_handle, size);
96
97 memset(&args, 0, sizeof(args));
98 args.handle = gem_handle;
99 drmIoctl(info->fd, DRM_IOCTL_GEM_CLOSE, &args);
100 return NULL;
101 }
102 } else {
103 buf->bo = rockchip_bo_create(info->rockchip, size, 0);
104 if (!buf->bo) {
105 ALOGE("failed to allocate bo %dx%dx%dx%d\n",
106 handle->height, pitch, cpp, size);
107 goto err;
108 }
109
110 gem_handle = rockchip_bo_handle(buf->bo);
111 ret = drmPrimeHandleToFD(info->fd, gem_handle, 0,
112 &handle->prime_fd);
113 ALOGV("Got fd %d for handle %d\n", handle->prime_fd, gem_handle);
114 if (ret) {
115 ALOGE("failed to get prime fd %d", ret);
116 goto err_unref;
117 }
118
119 buf->base.fb_handle = gem_handle;
120 }
121
122 handle->name = 0;
123 handle->stride = pitch;
124 buf->base.handle = handle;
125
126 return &buf->base;
127
128 err_unref:
129 rockchip_bo_destroy(buf->bo);
130 err:
131 free(buf);
132 return NULL;
133 }
134
drm_gem_rockchip_free(struct gralloc_drm_drv_t * drv,struct gralloc_drm_bo_t * bo)135 static void drm_gem_rockchip_free(struct gralloc_drm_drv_t *drv,
136 struct gralloc_drm_bo_t *bo)
137 {
138 struct rockchip_buffer *buf = (struct rockchip_buffer *)bo;
139
140 UNUSED(drv);
141
142 if (bo->handle && bo->handle->prime_fd)
143 close(bo->handle->prime_fd);
144
145 /* TODO: Is destroy correct here? */
146 rockchip_bo_destroy(buf->bo);
147 free(buf);
148 }
149
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)150 static int drm_gem_rockchip_map(struct gralloc_drm_drv_t *drv,
151 struct gralloc_drm_bo_t *bo, int x, int y, int w, int h,
152 int enable_write, void **addr)
153 {
154 struct rockchip_buffer *buf = (struct rockchip_buffer *)bo;
155
156 UNUSED(drv, x, y, w, h, enable_write);
157
158 *addr = rockchip_bo_map(buf->bo);
159 if (!*addr) {
160 ALOGE("failed to map bo\n");
161 return -1;
162 }
163
164 return 0;
165 }
166
drm_gem_rockchip_unmap(struct gralloc_drm_drv_t * drv,struct gralloc_drm_bo_t * bo)167 static void drm_gem_rockchip_unmap(struct gralloc_drm_drv_t *drv,
168 struct gralloc_drm_bo_t *bo)
169 {
170 UNUSED(drv, bo);
171 }
172
gralloc_drm_drv_create_for_rockchip(int fd)173 struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_rockchip(int fd)
174 {
175 struct rockchip_info *info;
176 int ret;
177
178 info = calloc(1, sizeof(*info));
179 if (!info) {
180 ALOGE("Failed to allocate rockchip gralloc device\n");
181 return NULL;
182 }
183
184 info->rockchip = rockchip_device_create(fd);
185 if (!info->rockchip) {
186 ALOGE("Failed to create new rockchip instance\n");
187 free(info);
188 return NULL;
189 }
190
191 info->fd = fd;
192 info->base.destroy = drm_gem_rockchip_destroy;
193 info->base.alloc = drm_gem_rockchip_alloc;
194 info->base.free = drm_gem_rockchip_free;
195 info->base.map = drm_gem_rockchip_map;
196 info->base.unmap = drm_gem_rockchip_unmap;
197
198 return &info->base;
199 }
200