+ return drv_modify_linear_combinations(drv);
+}
+
+static int exynos_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
+ uint32_t flags)
+{
+ size_t plane;
+
+ if (format == DRM_FORMAT_NV12) {
+ uint32_t chroma_height;
+ /* V4L2 s5p-mfc requires width to be 16 byte aligned and height 32. */
+ width = ALIGN(width, 16);
+ height = ALIGN(height, 32);
+ chroma_height = ALIGN(height / 2, 32);
+ bo->strides[0] = bo->strides[1] = width;
+ /* MFC v8+ requires 64 byte padding in the end of luma and chroma buffers. */
+ bo->sizes[0] = bo->strides[0] * height + 64;
+ bo->sizes[1] = bo->strides[1] * chroma_height + 64;
+ bo->offsets[0] = bo->offsets[1] = 0;
+ bo->total_size = bo->sizes[0] + bo->sizes[1];
+ } else if (format == DRM_FORMAT_XRGB8888 || format == DRM_FORMAT_ARGB8888) {
+ bo->strides[0] = drv_stride_from_format(format, width, 0);
+ bo->total_size = bo->sizes[0] = height * bo->strides[0];
+ bo->offsets[0] = 0;
+ } else {
+ fprintf(stderr, "drv: unsupported format %X\n", format);
+ assert(0);
+ return -EINVAL;
+ }
+
+ int ret;
+ for (plane = 0; plane < bo->num_planes; plane++) {
+ size_t size = bo->sizes[plane];
+ struct drm_exynos_gem_create gem_create;
+
+ memset(&gem_create, 0, sizeof(gem_create));
+ gem_create.size = size;
+ gem_create.flags = EXYNOS_BO_NONCONTIG;
+
+ ret = drmIoctl(bo->drv->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &gem_create);
+ if (ret) {
+ fprintf(stderr, "drv: DRM_IOCTL_EXYNOS_GEM_CREATE failed (size=%zu)\n",
+ size);
+ goto cleanup_planes;
+ }
+
+ bo->handles[plane].u32 = gem_create.handle;
+ }