// SPDX-License-Identifier: GPL-2.0
/*
 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
 * Author: James.Qian.Wang <james.qian.wang@arm.com>
 *
 */
#include <drm/drm_device.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>

#include "komeda_framebuffer.h"
#include "komeda_dev.h"

static void komeda_fb_destroy(struct drm_framebuffer *fb)
{
	struct komeda_fb *kfb = to_kfb(fb);
	u32 i;

	for (i = 0; i < fb->format->num_planes; i++)
		drm_gem_object_put(fb->obj[i]);

	drm_framebuffer_cleanup(fb);
	kfree(kfb);
}

static int komeda_fb_create_handle(struct drm_framebuffer *fb,
				   struct drm_file *file, u32 *handle)
{
	return drm_gem_handle_create(file, fb->obj[0], handle);
}

static const struct drm_framebuffer_funcs komeda_fb_funcs = {
	.destroy	= komeda_fb_destroy,
	.create_handle	= komeda_fb_create_handle,
};

static int
komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
			  const struct drm_mode_fb_cmd2 *mode_cmd)
{
	struct drm_framebuffer *fb = &kfb->base;
	const struct drm_format_info *info = fb->format;
	struct drm_gem_object *obj;
	u32 alignment_w = 0, alignment_h = 0, alignment_header, n_blocks, bpp;
	u64 min_size;

	obj = drm_gem_object_lookup(file, mode_cmd->handles[0]);
	if (!obj) {
		DRM_DEBUG_KMS("Failed to lookup GEM object\n");
		return -ENOENT;
	}

	switch (fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
	case AFBC_FORMAT_MOD_BLOCK_SIZE_32x8:
		alignment_w = 32;
		alignment_h = 8;
		break;
	case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
		alignment_w = 16;
		alignment_h = 16;
		break;
	default:
		WARN(1, "Invalid AFBC_FORMAT_MOD_BLOCK_SIZE: %lld.\n",
		     fb->modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK);
		break;
	}

	/* tiled header afbc */
	if (fb->modifier & AFBC_FORMAT_MOD_TILED) {
		alignment_w *= AFBC_TH_LAYOUT_ALIGNMENT;
		alignment_h *= AFBC_TH_LAYOUT_ALIGNMENT;
		alignment_header = AFBC_TH_BODY_START_ALIGNMENT;
	} else {
		alignment_header = AFBC_BODY_START_ALIGNMENT;
	}

	kfb->aligned_w = ALIGN(fb->width, alignment_w);
	kfb->aligned_h = ALIGN(fb->height, alignment_h);

	if (fb->offsets[0] % alignment_header) {
		DRM_DEBUG_KMS("afbc offset alignment check failed.\n");
		goto check_failed;
	}

	n_blocks = (kfb->aligned_w * kfb->aligned_h) / AFBC_SUPERBLK_PIXELS;
	kfb->offset_payload = ALIGN(n_blocks * AFBC_HEADER_SIZE,
				    alignment_header);

	bpp = komeda_get_afbc_format_bpp(info, fb->modifier);
	kfb->afbc_size = kfb->offset_payload + n_blocks *
			 ALIGN(bpp * AFBC_SUPERBLK_PIXELS / 8,
			       AFBC_SUPERBLK_ALIGNMENT);
	min_size = kfb->afbc_size + fb->offsets[0];
	if (min_size > obj->size) {
		DRM_DEBUG_KMS("afbc size check failed, obj_size: 0x%zx. min_size 0x%llx.\n",
			      obj->size, min_size);
		goto check_failed;
	}

	fb->obj[0] = obj;
	return 0;

check_failed:
	drm_gem_object_put(obj);
	return -EINVAL;
}

static int
komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb,
			       struct drm_file *file,
			       const struct drm_mode_fb_cmd2 *mode_cmd)
{
	struct drm_framebuffer *fb = &kfb->base;
	const struct drm_format_info *info = fb->format;
	struct drm_gem_object *obj;
	u32 i, block_h;
	u64 min_size;

	if (komeda_fb_check_src_coords(kfb, 0, 0, fb->width, fb->height))
		return -EINVAL;

	for (i = 0; i < info->num_planes; i++) {
		obj = drm_gem_object_lookup(file, mode_cmd->handles[i]);
		if (!obj) {
			DRM_DEBUG_KMS("Failed to lookup GEM object\n");
			return -ENOENT;
		}
		fb->obj[i] = obj;

		block_h = drm_format_info_block_height(info, i);
		if ((fb->pitches[i] * block_h) % mdev->chip.bus_width) {
			DRM_DEBUG_KMS("Pitch[%d]: 0x%x doesn't align to 0x%x\n",
				      i, fb->pitches[i], mdev->chip.bus_width);
			return -EINVAL;
		}

		min_size = komeda_fb_get_pixel_addr(kfb, 0, fb->height, i)
			 - to_drm_gem_cma_obj(obj)->paddr;
		if (obj->size < min_size) {
			DRM_DEBUG_KMS("The fb->obj[%d] size: 0x%zx lower than the minimum requirement: 0x%llx.\n",
				      i, obj->size, min_size);
			return -EINVAL;
		}
	}

	if (fb->format->num_planes == 3) {
		if (fb->pitches[1] != fb->pitches[2]) {
			DRM_DEBUG_KMS("The pitch[1] and [2] are not same\n");
			return -EINVAL;
		}
	}

	return 0;
}

struct drm_framebuffer *
komeda_fb_create(struct drm_device *dev, struct drm_file *file,
		 const struct drm_mode_fb_cmd2 *mode_cmd)
{
	struct komeda_dev *mdev = dev->dev_private;
	struct komeda_fb *kfb;
	int ret = 0, i;

	kfb = kzalloc(sizeof(*kfb), GFP_KERNEL);
	if (!kfb)
		return ERR_PTR(-ENOMEM);

	kfb->format_caps = komeda_get_format_caps(&mdev->fmt_tbl,
						  mode_cmd->pixel_format,
						  mode_cmd->modifier[0]);
	if (!kfb->format_caps) {
		DRM_DEBUG_KMS("FMT %x is not supported.\n",
			      mode_cmd->pixel_format);
		kfree(kfb);
		return ERR_PTR(-EINVAL);
	}

	drm_helper_mode_fill_fb_struct(dev, &kfb->base, mode_cmd);

	if (kfb->base.modifier)
		ret = komeda_fb_afbc_size_check(kfb, file, mode_cmd);
	else
		ret = komeda_fb_none_afbc_size_check(mdev, kfb, file, mode_cmd);
	if (ret < 0)
		goto err_cleanup;

	ret = drm_framebuffer_init(dev, &kfb->base, &komeda_fb_funcs);
	if (ret < 0) {
		DRM_DEBUG_KMS("failed to initialize fb\n");

		goto err_cleanup;
	}

	kfb->is_va = mdev->iommu ? true : false;

	return &kfb->base;

err_cleanup:
	for (i = 0; i < kfb->base.format->num_planes; i++)
		drm_gem_object_put(kfb->base.obj[i]);

	kfree(kfb);
	return ERR_PTR(ret);
}

int komeda_fb_check_src_coords(const struct komeda_fb *kfb,
			       u32 src_x, u32 src_y, u32 src_w, u32 src_h)
{
	const struct drm_framebuffer *fb = &kfb->base;
	const struct drm_format_info *info = fb->format;
	u32 block_w = drm_format_info_block_width(fb->format, 0);
	u32 block_h = drm_format_info_block_height(fb->format, 0);

	if ((src_x + src_w > fb->width) || (src_y + src_h > fb->height)) {
		DRM_DEBUG_ATOMIC("Invalid source coordinate.\n");
		return -EINVAL;
	}

	if ((src_x % info->hsub) || (src_w % info->hsub) ||
	    (src_y % info->vsub) || (src_h % info->vsub)) {
		DRM_DEBUG_ATOMIC("Wrong subsampling dimension x:%d, y:%d, w:%d, h:%d for format: %x.\n",
				 src_x, src_y, src_w, src_h, info->format);
		return -EINVAL;
	}

	if ((src_x % block_w) || (src_w % block_w) ||
	    (src_y % block_h) || (src_h % block_h)) {
		DRM_DEBUG_ATOMIC("x:%d, y:%d, w:%d, h:%d should be multiple of block_w/h for format: %x.\n",
				 src_x, src_y, src_w, src_h, info->format);
		return -EINVAL;
	}

	return 0;
}

dma_addr_t
komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)
{
	struct drm_framebuffer *fb = &kfb->base;
	const struct drm_gem_cma_object *obj;
	u32 offset, plane_x, plane_y, block_w, block_sz;

	if (plane >= fb->format->num_planes) {
		DRM_DEBUG_KMS("Out of max plane num.\n");
		return -EINVAL;
	}

	obj = drm_fb_cma_get_gem_obj(fb, plane);

	offset = fb->offsets[plane];
	if (!fb->modifier) {
		block_w = drm_format_info_block_width(fb->format, plane);
		block_sz = fb->format->char_per_block[plane];
		plane_x = x / (plane ? fb->format->hsub : 1);
		plane_y = y / (plane ? fb->format->vsub : 1);

		offset += (plane_x / block_w) * block_sz
			+ plane_y * fb->pitches[plane];
	}

	return obj->paddr + offset;
}

/* if the fb can be supported by a specific layer */
bool komeda_fb_is_layer_supported(struct komeda_fb *kfb, u32 layer_type,
				  u32 rot)
{
	struct drm_framebuffer *fb = &kfb->base;
	struct komeda_dev *mdev = fb->dev->dev_private;
	u32 fourcc = fb->format->format;
	u64 modifier = fb->modifier;
	bool supported;

	supported = komeda_format_mod_supported(&mdev->fmt_tbl, layer_type,
						fourcc, modifier, rot);
	if (!supported)
		DRM_DEBUG_ATOMIC("Layer TYPE: %d doesn't support fb FMT: %p4cc with modifier: 0x%llx.\n",
				 layer_type, &fourcc, modifier);

	return supported;
}
