+
+ for (plane = 0; plane < bo->num_planes; plane++)
+ bo->handles[plane].u32 = gem_create.handle;
+
+ return 0;
+}
+
+static int rockchip_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t use_flags)
+{
+ uint64_t modifiers[] = { DRM_FORMAT_MOD_LINEAR };
+ return rockchip_bo_create_with_modifiers(bo, width, height, format, modifiers,
+ ARRAY_SIZE(modifiers));
+}
+
+static void *rockchip_bo_map(struct bo *bo, struct map_info *data, size_t plane, uint32_t map_flags)
+{
+ int ret;
+ struct drm_rockchip_gem_map_off gem_map;
+ struct rockchip_private_map_data *priv;
+
+ /* We can only map buffers created with SW access flags, which should
+ * have no modifiers (ie, not AFBC). */
+ if (bo->format_modifiers[0] == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC)
+ return MAP_FAILED;
+
+ memset(&gem_map, 0, sizeof(gem_map));
+ gem_map.handle = bo->handles[0].u32;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &gem_map);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET failed\n");
+ return MAP_FAILED;
+ }
+
+ void *addr = mmap(0, bo->total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
+ gem_map.offset);
+
+ data->length = bo->total_size;
+
+ if (bo->use_flags & BO_USE_RENDERSCRIPT) {
+ priv = calloc(1, sizeof(*priv));
+ priv->cached_addr = calloc(1, bo->total_size);
+ priv->gem_addr = addr;
+ memcpy(priv->cached_addr, priv->gem_addr, bo->total_size);
+ data->priv = priv;
+ addr = priv->cached_addr;
+ }
+
+ return addr;
+}
+
+static int rockchip_bo_unmap(struct bo *bo, struct map_info *data)
+{
+ if (data->priv) {
+ struct rockchip_private_map_data *priv = data->priv;
+ data->addr = priv->gem_addr;
+ free(priv->cached_addr);
+ free(priv);
+ data->priv = NULL;
+ }
+
+ return munmap(data->addr, data->length);
+}
+
+static int rockchip_bo_flush(struct bo *bo, struct map_info *data)
+{
+ struct rockchip_private_map_data *priv = data->priv;
+ if (priv && (data->map_flags & BO_MAP_WRITE))
+ memcpy(priv->gem_addr, priv->cached_addr, bo->total_size);
+
+ return 0;
+}
+
+static uint32_t rockchip_resolve_format(uint32_t format, uint64_t use_flags)
+{
+ switch (format) {
+ case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
+ /* Camera subsystem requires NV12. */
+ if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))
+ return DRM_FORMAT_NV12;
+ /*HACK: See b/28671744 */
+ return DRM_FORMAT_XBGR8888;
+ case DRM_FORMAT_FLEX_YCbCr_420_888:
+ return DRM_FORMAT_NV12;
+ default:
+ return format;
+ }
+}
+
+struct backend backend_rockchip = {
+ .name = "rockchip",
+ .init = rockchip_init,
+ .bo_create = rockchip_bo_create,
+ .bo_create_with_modifiers = rockchip_bo_create_with_modifiers,
+ .bo_destroy = drv_gem_bo_destroy,
+ .bo_import = drv_prime_bo_import,
+ .bo_map = rockchip_bo_map,
+ .bo_unmap = rockchip_bo_unmap,
+ .bo_flush = rockchip_bo_flush,
+ .resolve_format = rockchip_resolve_format,