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