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 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 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 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 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 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 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