// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2022 MediaTek Inc.
 * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
 */

#include <linux/remoteproc.h>
#include <linux/remoteproc/mtk_scp.h>
#include "mtk-mdp3-vpu.h"
#include "mtk-mdp3-core.h"

#define MDP_VPU_MESSAGE_TIMEOUT 500U
#define vpu_alloc_size		0x600000

static inline struct mdp_dev *vpu_to_mdp(struct mdp_vpu_dev *vpu)
{
	return container_of(vpu, struct mdp_dev, vpu);
}

static int mdp_vpu_shared_mem_alloc(struct mdp_vpu_dev *vpu)
{
	if (vpu->work && vpu->work_addr)
		return 0;

	vpu->work = dma_alloc_coherent(scp_get_device(vpu->scp), vpu_alloc_size,
				       &vpu->work_addr, GFP_KERNEL);

	if (!vpu->work)
		return -ENOMEM;
	else
		return 0;
}

void mdp_vpu_shared_mem_free(struct mdp_vpu_dev *vpu)
{
	if (vpu->work && vpu->work_addr)
		dma_free_coherent(scp_get_device(vpu->scp), vpu_alloc_size,
				  vpu->work, vpu->work_addr);
}

static void mdp_vpu_ipi_handle_init_ack(void *data, unsigned int len,
					void *priv)
{
	struct mdp_ipi_init_msg *msg = (struct mdp_ipi_init_msg *)data;
	struct mdp_vpu_dev *vpu =
		(struct mdp_vpu_dev *)(unsigned long)msg->drv_data;

	if (!vpu->work_size)
		vpu->work_size = msg->work_size;

	vpu->status = msg->status;
	complete(&vpu->ipi_acked);
}

static void mdp_vpu_ipi_handle_deinit_ack(void *data, unsigned int len,
					  void *priv)
{
	struct mdp_ipi_deinit_msg *msg = (struct mdp_ipi_deinit_msg *)data;
	struct mdp_vpu_dev *vpu =
		(struct mdp_vpu_dev *)(unsigned long)msg->drv_data;

	vpu->status = msg->status;
	complete(&vpu->ipi_acked);
}

static void mdp_vpu_ipi_handle_frame_ack(void *data, unsigned int len,
					 void *priv)
{
	struct img_sw_addr *addr = (struct img_sw_addr *)data;
	struct img_ipi_frameparam *param =
		(struct img_ipi_frameparam *)(unsigned long)addr->va;
	struct mdp_vpu_ctx *ctx =
		(struct mdp_vpu_ctx *)(unsigned long)param->drv_data;

	if (param->state) {
		struct mdp_dev *mdp = vpu_to_mdp(ctx->vpu_dev);

		dev_err(&mdp->pdev->dev, "VPU MDP failure:%d\n", param->state);
	}
	ctx->vpu_dev->status = param->state;
	complete(&ctx->vpu_dev->ipi_acked);
}

int mdp_vpu_register(struct mdp_dev *mdp)
{
	int err;
	struct mtk_scp *scp = mdp->scp;
	struct device *dev = &mdp->pdev->dev;

	err = scp_ipi_register(scp, SCP_IPI_MDP_INIT,
			       mdp_vpu_ipi_handle_init_ack, NULL);
	if (err) {
		dev_err(dev, "scp_ipi_register failed %d\n", err);
		goto err_ipi_init;
	}
	err = scp_ipi_register(scp, SCP_IPI_MDP_DEINIT,
			       mdp_vpu_ipi_handle_deinit_ack, NULL);
	if (err) {
		dev_err(dev, "scp_ipi_register failed %d\n", err);
		goto err_ipi_deinit;
	}
	err = scp_ipi_register(scp, SCP_IPI_MDP_FRAME,
			       mdp_vpu_ipi_handle_frame_ack, NULL);
	if (err) {
		dev_err(dev, "scp_ipi_register failed %d\n", err);
		goto err_ipi_frame;
	}
	return 0;

err_ipi_frame:
	scp_ipi_unregister(scp, SCP_IPI_MDP_DEINIT);
err_ipi_deinit:
	scp_ipi_unregister(scp, SCP_IPI_MDP_INIT);
err_ipi_init:

	return err;
}

void mdp_vpu_unregister(struct mdp_dev *mdp)
{
	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_INIT);
	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_DEINIT);
	scp_ipi_unregister(mdp->scp, SCP_IPI_MDP_FRAME);
}

static int mdp_vpu_sendmsg(struct mdp_vpu_dev *vpu, enum scp_ipi_id id,
			   void *buf, unsigned int len)
{
	struct mdp_dev *mdp = vpu_to_mdp(vpu);
	unsigned int t = MDP_VPU_MESSAGE_TIMEOUT;
	int ret;

	if (!vpu->scp) {
		dev_dbg(&mdp->pdev->dev, "vpu scp is NULL");
		return -EINVAL;
	}
	ret = scp_ipi_send(vpu->scp, id, buf, len, 2000);

	if (ret) {
		dev_err(&mdp->pdev->dev, "scp_ipi_send failed %d\n", ret);
		return -EPERM;
	}
	ret = wait_for_completion_timeout(&vpu->ipi_acked,
					  msecs_to_jiffies(t));
	if (!ret)
		ret = -ETIME;
	else if (vpu->status)
		ret = -EINVAL;
	else
		ret = 0;
	return ret;
}

int mdp_vpu_dev_init(struct mdp_vpu_dev *vpu, struct mtk_scp *scp,
		     struct mutex *lock)
{
	struct mdp_ipi_init_msg msg = {
		.drv_data = (unsigned long)vpu,
	};
	size_t mem_size;
	phys_addr_t pool;
	const size_t pool_size = sizeof(struct mdp_config_pool);
	struct mdp_dev *mdp = vpu_to_mdp(vpu);
	int err;

	init_completion(&vpu->ipi_acked);
	vpu->scp = scp;
	vpu->lock = lock;
	vpu->work_size = 0;
	err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
	if (err)
		goto err_work_size;
	/* vpu work_size was set in mdp_vpu_ipi_handle_init_ack */

	mem_size = vpu_alloc_size;
	if (mdp_vpu_shared_mem_alloc(vpu)) {
		dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
		goto err_mem_alloc;
	}

	pool = ALIGN((uintptr_t)vpu->work + vpu->work_size, 8);
	if (pool + pool_size - (uintptr_t)vpu->work > mem_size) {
		dev_err(&mdp->pdev->dev,
			"VPU memory insufficient: %zx + %zx > %zx",
			vpu->work_size, pool_size, mem_size);
		err = -ENOMEM;
		goto err_mem_size;
	}

	dev_dbg(&mdp->pdev->dev,
		"VPU work:%pK pa:%pad sz:%zx pool:%pa sz:%zx (mem sz:%zx)",
		vpu->work, &vpu->work_addr, vpu->work_size,
		&pool, pool_size, mem_size);
	vpu->pool = (struct mdp_config_pool *)(uintptr_t)pool;
	msg.work_addr = vpu->work_addr;
	msg.work_size = vpu->work_size;
	err = mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_INIT, &msg, sizeof(msg));
	if (err)
		goto err_work_size;

	memset(vpu->pool, 0, sizeof(*vpu->pool));
	return 0;

err_work_size:
	switch (vpu->status) {
	case -MDP_IPI_EBUSY:
		err = -EBUSY;
		break;
	case -MDP_IPI_ENOMEM:
		err = -ENOSPC;	/* -ENOMEM */
		break;
	}
	return err;
err_mem_size:
err_mem_alloc:
	return err;
}

int mdp_vpu_dev_deinit(struct mdp_vpu_dev *vpu)
{
	struct mdp_ipi_deinit_msg msg = {
		.drv_data = (unsigned long)vpu,
		.work_addr = vpu->work_addr,
	};

	return mdp_vpu_sendmsg(vpu, SCP_IPI_MDP_DEINIT, &msg, sizeof(msg));
}

static struct img_config *mdp_config_get(struct mdp_vpu_dev *vpu,
					 enum mdp_config_id id, uint32_t *addr)
{
	struct img_config *config;

	if (id < 0 || id >= MDP_CONFIG_POOL_SIZE)
		return ERR_PTR(-EINVAL);

	mutex_lock(vpu->lock);
	vpu->pool->cfg_count[id]++;
	config = &vpu->pool->configs[id];
	*addr = vpu->work_addr + ((uintptr_t)config - (uintptr_t)vpu->work);
	mutex_unlock(vpu->lock);

	return config;
}

static int mdp_config_put(struct mdp_vpu_dev *vpu,
			  enum mdp_config_id id,
			  const struct img_config *config)
{
	int err = 0;

	if (id < 0 || id >= MDP_CONFIG_POOL_SIZE)
		return -EINVAL;
	if (vpu->lock)
		mutex_lock(vpu->lock);
	if (!vpu->pool->cfg_count[id] || config != &vpu->pool->configs[id])
		err = -EINVAL;
	else
		vpu->pool->cfg_count[id]--;
	if (vpu->lock)
		mutex_unlock(vpu->lock);
	return err;
}

int mdp_vpu_ctx_init(struct mdp_vpu_ctx *ctx, struct mdp_vpu_dev *vpu,
		     enum mdp_config_id id)
{
	ctx->config = mdp_config_get(vpu, id, &ctx->inst_addr);
	if (IS_ERR(ctx->config)) {
		int err = PTR_ERR(ctx->config);

		ctx->config = NULL;
		return err;
	}
	ctx->config_id = id;
	ctx->vpu_dev = vpu;
	return 0;
}

int mdp_vpu_ctx_deinit(struct mdp_vpu_ctx *ctx)
{
	int err = mdp_config_put(ctx->vpu_dev, ctx->config_id, ctx->config);

	ctx->config_id = 0;
	ctx->config = NULL;
	ctx->inst_addr = 0;
	return err;
}

int mdp_vpu_process(struct mdp_vpu_ctx *ctx, struct img_ipi_frameparam *param)
{
	struct mdp_vpu_dev *vpu = ctx->vpu_dev;
	struct mdp_dev *mdp = vpu_to_mdp(vpu);
	struct img_sw_addr addr;

	if (!ctx->vpu_dev->work || !ctx->vpu_dev->work_addr) {
		if (mdp_vpu_shared_mem_alloc(vpu)) {
			dev_err(&mdp->pdev->dev, "VPU memory alloc fail!");
			return -ENOMEM;
		}
	}
	memset((void *)ctx->vpu_dev->work, 0, ctx->vpu_dev->work_size);
	memset(ctx->config, 0, sizeof(*ctx->config));
	param->config_data.va = (unsigned long)ctx->config;
	param->config_data.pa = ctx->inst_addr;
	param->drv_data = (unsigned long)ctx;

	memcpy((void *)ctx->vpu_dev->work, param, sizeof(*param));
	addr.pa = ctx->vpu_dev->work_addr;
	addr.va = (uintptr_t)ctx->vpu_dev->work;
	return mdp_vpu_sendmsg(ctx->vpu_dev, SCP_IPI_MDP_FRAME,
		&addr, sizeof(addr));
}
