// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2023 Loongson Technology Corporation Limited
 */

#include <linux/dma-buf.h>

#include <drm/drm_debugfs.h>
#include <drm/drm_file.h>
#include <drm/drm_gem.h>
#include <drm/drm_prime.h>

#include "lsdc_drv.h"
#include "lsdc_gem.h"
#include "lsdc_ttm.h"

static int lsdc_gem_prime_pin(struct drm_gem_object *obj)
{
	struct lsdc_bo *lbo = gem_to_lsdc_bo(obj);
	int ret;

	dma_resv_assert_held(obj->resv);

	ret = lsdc_bo_pin(lbo, LSDC_GEM_DOMAIN_GTT, NULL);
	if (likely(ret == 0))
		lbo->sharing_count++;

	return ret;
}

static void lsdc_gem_prime_unpin(struct drm_gem_object *obj)
{
	struct lsdc_bo *lbo = gem_to_lsdc_bo(obj);

	dma_resv_assert_held(obj->resv);

	lsdc_bo_unpin(lbo);
	if (lbo->sharing_count)
		lbo->sharing_count--;
}

static struct sg_table *lsdc_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
	struct ttm_buffer_object *tbo = to_ttm_bo(obj);
	struct ttm_tt *tt = tbo->ttm;

	if (!tt) {
		drm_err(obj->dev, "sharing a buffer without backing memory\n");
		return ERR_PTR(-ENOMEM);
	}

	return drm_prime_pages_to_sg(obj->dev, tt->pages, tt->num_pages);
}

static void lsdc_gem_object_free(struct drm_gem_object *obj)
{
	struct ttm_buffer_object *tbo = to_ttm_bo(obj);

	if (tbo)
		ttm_bo_put(tbo);
}

static int lsdc_gem_object_vmap(struct drm_gem_object *obj, struct iosys_map *map)
{
	struct ttm_buffer_object *tbo = to_ttm_bo(obj);
	struct lsdc_bo *lbo = to_lsdc_bo(tbo);
	int ret;

	if (lbo->vmap_count > 0) {
		++lbo->vmap_count;
		goto out;
	}

	ret = lsdc_bo_pin(lbo, 0, NULL);
	if (unlikely(ret)) {
		drm_err(obj->dev, "pin %p for vmap failed\n", lbo);
		return ret;
	}

	ret = ttm_bo_vmap(tbo, &lbo->map);
	if (ret) {
		drm_err(obj->dev, "ttm bo vmap failed\n");
		lsdc_bo_unpin(lbo);
		return ret;
	}

	lbo->vmap_count = 1;

out:
	*map = lbo->map;

	return 0;
}

static void lsdc_gem_object_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
{
	struct ttm_buffer_object *tbo = to_ttm_bo(obj);
	struct lsdc_bo *lbo = to_lsdc_bo(tbo);

	if (unlikely(!lbo->vmap_count)) {
		drm_warn(obj->dev, "%p is not mapped\n", lbo);
		return;
	}

	--lbo->vmap_count;
	if (lbo->vmap_count == 0) {
		ttm_bo_vunmap(tbo, &lbo->map);

		lsdc_bo_unpin(lbo);
	}
}

static int lsdc_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
	struct ttm_buffer_object *tbo = to_ttm_bo(obj);
	int ret;

	ret = ttm_bo_mmap_obj(vma, tbo);
	if (unlikely(ret)) {
		drm_warn(obj->dev, "mmap %p failed\n", tbo);
		return ret;
	}

	drm_gem_object_put(obj);

	return 0;
}

static const struct drm_gem_object_funcs lsdc_gem_object_funcs = {
	.free = lsdc_gem_object_free,
	.export = drm_gem_prime_export,
	.pin = lsdc_gem_prime_pin,
	.unpin = lsdc_gem_prime_unpin,
	.get_sg_table = lsdc_gem_prime_get_sg_table,
	.vmap = lsdc_gem_object_vmap,
	.vunmap = lsdc_gem_object_vunmap,
	.mmap = lsdc_gem_object_mmap,
};

struct drm_gem_object *lsdc_gem_object_create(struct drm_device *ddev,
					      u32 domain,
					      size_t size,
					      bool kerenl,
					      struct sg_table *sg,
					      struct dma_resv *resv)
{
	struct lsdc_device *ldev = to_lsdc(ddev);
	struct drm_gem_object *gobj;
	struct lsdc_bo *lbo;
	int ret;

	lbo = lsdc_bo_create(ddev, domain, size, kerenl, sg, resv);
	if (IS_ERR(lbo)) {
		ret = PTR_ERR(lbo);
		return ERR_PTR(ret);
	}

	if (!sg) {
		/* VRAM is filled with random data */
		lsdc_bo_clear(lbo);
	}

	gobj = &lbo->tbo.base;
	gobj->funcs = &lsdc_gem_object_funcs;

	/* tracking the BOs we created */
	mutex_lock(&ldev->gem.mutex);
	list_add_tail(&lbo->list, &ldev->gem.objects);
	mutex_unlock(&ldev->gem.mutex);

	return gobj;
}

struct drm_gem_object *
lsdc_prime_import_sg_table(struct drm_device *ddev,
			   struct dma_buf_attachment *attach,
			   struct sg_table *sg)
{
	struct dma_resv *resv = attach->dmabuf->resv;
	u64 size = attach->dmabuf->size;
	struct drm_gem_object *gobj;
	struct lsdc_bo *lbo;

	dma_resv_lock(resv, NULL);
	gobj = lsdc_gem_object_create(ddev, LSDC_GEM_DOMAIN_GTT, size, false,
				      sg, resv);
	dma_resv_unlock(resv);

	if (IS_ERR(gobj)) {
		drm_err(ddev, "Failed to import sg table\n");
		return gobj;
	}

	lbo = gem_to_lsdc_bo(gobj);
	lbo->sharing_count = 1;

	return gobj;
}

int lsdc_dumb_create(struct drm_file *file, struct drm_device *ddev,
		     struct drm_mode_create_dumb *args)
{
	struct lsdc_device *ldev = to_lsdc(ddev);
	const struct lsdc_desc *descp = ldev->descp;
	u32 domain = LSDC_GEM_DOMAIN_VRAM;
	struct drm_gem_object *gobj;
	size_t size;
	u32 pitch;
	u32 handle;
	int ret;

	if (!args->width || !args->height)
		return -EINVAL;

	if (args->bpp != 32 && args->bpp != 16)
		return -EINVAL;

	pitch = args->width * args->bpp / 8;
	pitch = ALIGN(pitch, descp->pitch_align);
	size = pitch * args->height;
	size = ALIGN(size, PAGE_SIZE);

	/* Maximum single bo size allowed is the half vram size available */
	if (size > ldev->vram_size / 2) {
		drm_err(ddev, "Requesting(%zuMiB) failed\n", size >> 20);
		return -ENOMEM;
	}

	gobj = lsdc_gem_object_create(ddev, domain, size, false, NULL, NULL);
	if (IS_ERR(gobj)) {
		drm_err(ddev, "Failed to create gem object\n");
		return PTR_ERR(gobj);
	}

	ret = drm_gem_handle_create(file, gobj, &handle);

	/* drop reference from allocate, handle holds it now */
	drm_gem_object_put(gobj);
	if (ret)
		return ret;

	args->pitch = pitch;
	args->size = size;
	args->handle = handle;

	return 0;
}

int lsdc_dumb_map_offset(struct drm_file *filp, struct drm_device *ddev,
			 u32 handle, uint64_t *offset)
{
	struct drm_gem_object *gobj;

	gobj = drm_gem_object_lookup(filp, handle);
	if (!gobj)
		return -ENOENT;

	*offset = drm_vma_node_offset_addr(&gobj->vma_node);

	drm_gem_object_put(gobj);

	return 0;
}

void lsdc_gem_init(struct drm_device *ddev)
{
	struct lsdc_device *ldev = to_lsdc(ddev);

	mutex_init(&ldev->gem.mutex);
	INIT_LIST_HEAD(&ldev->gem.objects);
}

int lsdc_show_buffer_object(struct seq_file *m, void *arg)
{
	struct drm_info_node *node = (struct drm_info_node *)m->private;
	struct drm_device *ddev = node->minor->dev;
	struct lsdc_device *ldev = to_lsdc(ddev);
	struct lsdc_bo *lbo;
	unsigned int i;

	mutex_lock(&ldev->gem.mutex);

	i = 0;

	list_for_each_entry(lbo, &ldev->gem.objects, list) {
		struct ttm_buffer_object *tbo = &lbo->tbo;
		struct ttm_resource *resource = tbo->resource;

		seq_printf(m, "bo[%04u][%p]: size: %8zuKiB %s offset: %8llx\n",
			   i, lbo, lsdc_bo_size(lbo) >> 10,
			   lsdc_mem_type_to_str(resource->mem_type),
			   lsdc_bo_gpu_offset(lbo));
		i++;
	}

	mutex_unlock(&ldev->gem.mutex);

	seq_printf(m, "Pinned BO size: VRAM: %zuKiB, GTT: %zu KiB\n",
		   ldev->vram_pinned_size >> 10, ldev->gtt_pinned_size >> 10);

	return 0;
}
