/*
 * Copyright 2014 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifdef DRV_EXYNOS

// clang-format off
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <xf86drm.h>
#include <exynos_drm.h>
// clang-format on

#include "drv_priv.h"
#include "helpers.h"
#include "util.h"

static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 };

static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12 };

static int exynos_init(struct driver *drv)
{
	drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
			     &LINEAR_METADATA, BO_USE_RENDER_MASK);

	drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats),
			     &LINEAR_METADATA, BO_USE_TEXTURE_MASK);

	return drv_modify_linear_combinations(drv);
}

static int exynos_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
			    uint64_t use_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->meta.strides[0] = bo->meta.strides[1] = width;
		/* MFC v8+ requires 64 byte padding in the end of luma and chroma buffers. */
		bo->meta.sizes[0] = bo->meta.strides[0] * height + 64;
		bo->meta.sizes[1] = bo->meta.strides[1] * chroma_height + 64;
		bo->meta.offsets[0] = bo->meta.offsets[1] = 0;
		bo->meta.total_size = bo->meta.sizes[0] + bo->meta.sizes[1];
	} else if (format == DRM_FORMAT_XRGB8888 || format == DRM_FORMAT_ARGB8888) {
		bo->meta.strides[0] = drv_stride_from_format(format, width, 0);
		bo->meta.total_size = bo->meta.sizes[0] = height * bo->meta.strides[0];
		bo->meta.offsets[0] = 0;
	} else {
		drv_log("unsupported format %X\n", format);
		assert(0);
		return -EINVAL;
	}

	int ret;
	for (plane = 0; plane < bo->meta.num_planes; plane++) {
		size_t size = bo->meta.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) {
			drv_log("DRM_IOCTL_EXYNOS_GEM_CREATE failed (size=%zu)\n", size);
			ret = -errno;
			goto cleanup_planes;
		}

		bo->handles[plane].u32 = gem_create.handle;
	}

	return 0;

cleanup_planes:
	for (; plane != 0; plane--) {
		struct drm_gem_close gem_close;
		memset(&gem_close, 0, sizeof(gem_close));
		gem_close.handle = bo->handles[plane - 1].u32;
		int gem_close_ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
		if (gem_close_ret) {
			drv_log("DRM_IOCTL_GEM_CLOSE failed: %d\n", gem_close_ret);
		}
	}

	return ret;
}

/*
 * Use dumb mapping with exynos even though a GEM buffer is created.
 * libdrm does the same thing in exynos_drm.c
 */
const struct backend backend_exynos = {
	.name = "exynos",
	.init = exynos_init,
	.bo_create = exynos_bo_create,
	.bo_destroy = drv_gem_bo_destroy,
	.bo_import = drv_prime_bo_import,
	.bo_map = drv_dumb_bo_map,
	.bo_unmap = drv_bo_munmap,
};

#endif
