/*
 * drivers/amlogic/media/stream_input/parser/stream_bufffer_interface.c
 *
 * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 */
#define DEBUG
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/frame_sync/tsync_pcr.h>
#include "../../frame_provider/decoder/utils/vdec.h"
#include "../../common/chips/decoder_cpu_ver_info.h"
#include "stream_buffer_base.h"
#include "amports_priv.h"
#include "thread_rw.h"

#define MEM_NAME "stbuf"
#define MAP_RANGE (SZ_1M)

static void stream_buffer_release(struct stream_buf_s *stbuf);

static const char *type_to_str(int t)
{
	switch (t) {
	case BUF_TYPE_VIDEO:
		return "VIDEO";
	case BUF_TYPE_AUDIO:
		return "AUDIO";
	case BUF_TYPE_SUBTITLE:
		return "SUB";
	case BUF_TYPE_USERDATA:
		return "USER";
	case BUF_TYPE_HEVC:
		return "HEVC";
	default:
		return "ERR";
	}
}

static int stream_buffer_init(struct stream_buf_s *stbuf, struct vdec_s *vdec)
{
	int ret = 0;
	u32 flags = CODEC_MM_FLAGS_DMA;
	bool is_secure = 0;
	u32 addr = 0;
	int pages = 0;
	u32 size;

	if (stbuf->buf_start)
		return 0;

	snprintf(stbuf->name, sizeof(stbuf->name),
		"%s-%d", MEM_NAME, vdec->id);

	if (stbuf->ext_buf_addr) {
		addr	= stbuf->ext_buf_addr;
		size	= stbuf->buf_size;
		is_secure = stbuf->is_secure;
		pages = (size >> PAGE_SHIFT);
	} else {
		flags |= CODEC_MM_FLAGS_FOR_VDECODER;
		if (vdec->port_flag & PORT_FLAG_DRM) {
			flags |= CODEC_MM_FLAGS_TVP;
			is_secure = true;
		}

		size = PAGE_ALIGN(stbuf->buf_size);
		pages = (size >> PAGE_SHIFT);
		addr = codec_mm_alloc_for_dma(stbuf->name,
				pages, PAGE_SHIFT + 4, flags);
		if (!addr) {
			ret = -ENOMEM;
			goto err;
		}
		stbuf->use_ptsserv = 1;
	}
	vdec_config_vld_reg(vdec, addr, size);

	ret = vdec_set_input_buffer(vdec, addr, size);
	if (ret) {
		pr_err("[%d]: set input buffer err.\n", stbuf->id);
		goto err;
	}

	atomic_set(&stbuf->payload, 0);
	init_waitqueue_head(&stbuf->wq);

	stbuf->buf_start	= addr;
	stbuf->buf_wp		= addr;
	stbuf->buf_rp		= addr;
	stbuf->buf_size		= size;
	stbuf->is_secure	= is_secure;
	stbuf->no_parser	= true;
	stbuf->buf_page_num	= pages;
	stbuf->canusebuf_size	= size;
	stbuf->stream_offset	= 0;

	/* init thread write. */
	if (!(vdec_get_debug_flags() & 1) &&
		!codec_mm_video_tvp_enabled() &&
		(!stbuf->ext_buf_addr)) {
		int block_size = PAGE_SIZE << 4;
		int buf_num = (2 * SZ_1M) / (PAGE_SIZE << 4);

		stbuf->write_thread =
			threadrw_alloc(buf_num, block_size,
				       stream_buffer_write_ex, 0);
	}

	stbuf->flag |= BUF_FLAG_ALLOC;
	stbuf->flag |= BUF_FLAG_IN_USE;
	if (vdec_single(vdec))
		pts_start(stbuf->type);
	pr_info("[%d]: [%s-%s] addr: %lx, size: %x, thrRW: %d, extbuf: %d, secure: %d\n",
		stbuf->id, type_to_str(stbuf->type), stbuf->name,
		stbuf->buf_start, stbuf->buf_size,
		!!stbuf->write_thread,
		!!stbuf->ext_buf_addr,
		stbuf->is_secure);

	return 0;
err:
	stream_buffer_release(stbuf);

	return ret;
}

static void stream_buffer_release(struct stream_buf_s *stbuf)
{
	if (stbuf->write_thread)
		threadrw_release(stbuf);
	if (vdec_single(container_of(stbuf, struct vdec_s, vbuf)))
		pts_stop(stbuf->type);

	if (stbuf->flag & BUF_FLAG_ALLOC && stbuf->buf_start) {
		if (!stbuf->ext_buf_addr)
			codec_mm_free_for_dma(MEM_NAME, stbuf->buf_start);

		stbuf->flag		&= ~BUF_FLAG_ALLOC;
		stbuf->ext_buf_addr	= 0;
		stbuf->buf_start	= 0;
		stbuf->is_secure	= false;
	}
	stbuf->flag &= ~BUF_FLAG_IN_USE;
}

static int get_free_space(struct stream_buf_s *stbuf)
{
	u32 len = stbuf->buf_size;
	int idle = 0;

	if (!atomic_read(&stbuf->payload) && (stbuf->buf_rp == stbuf->buf_wp))
		idle = len;
	else if (stbuf->buf_wp > stbuf->buf_rp)
		idle = len - (stbuf->buf_wp - stbuf->buf_rp);
	else if (stbuf->buf_wp < stbuf->buf_rp)
		idle = stbuf->buf_rp - stbuf->buf_wp;

	/*pr_info("[%d]: wp: %x, rp: %x, payload: %d, free space: %d\n",
		stbuf->id, stbuf->buf_wp, stbuf->buf_rp,
		atomic_read(&stbuf->payload), idle);*/

	return idle;
}

static int aml_copy_from_user(void *to, const void *from, ulong n)
{
	int ret =0;

	if (likely(access_ok(from, n)))
		ret = copy_from_user(to, from, n);
	else
		memcpy(to, from, n);

	return ret;
}

static int stream_buffer_copy(struct stream_buf_s *stbuf, const u8 *buf, u32 size)
{
	int ret = 0;
	void *src = NULL, *dst = NULL;
	int i, len;

	for (i = 0; i < size; i += MAP_RANGE) {
		len = ((size - i) > MAP_RANGE) ? MAP_RANGE : size - i;
		src = stbuf->is_phybuf ?
			codec_mm_vmap((ulong) buf + i, len) :
			(void *) buf;
		dst = codec_mm_vmap(stbuf->buf_wp + i, len);
		if (!src || !dst) {
			ret = -EFAULT;
			pr_err("[%d]: %s, src or dst is invalid.\n",
				stbuf->id,  __func__);
			goto err;
		}

		if (aml_copy_from_user(dst, src, len)) {
			ret = -EAGAIN;
			goto err;
		}

		codec_mm_dma_flush(dst, len, DMA_TO_DEVICE);
		codec_mm_unmap_phyaddr(dst);

		if (stbuf->is_phybuf)
			codec_mm_unmap_phyaddr(src);
	}

	return 0;
err:
	if (stbuf->is_phybuf && src)
		codec_mm_unmap_phyaddr(src);
	if (dst)
		codec_mm_unmap_phyaddr(dst);
	return ret;
}

static int rb_push_data(struct stream_buf_s *stbuf, const u8 *in, u32 size)
{
	int ret, len;
	u32 wp = stbuf->buf_wp;
	u32 sp = (stbuf->buf_wp + size);
	u32 ep = (stbuf->buf_start + stbuf->buf_size);

	len = sp > ep ? ep - wp : size;

	if (!stbuf->ext_buf_addr) {
		ret = stream_buffer_copy(stbuf, in, len);
		if (ret)
			return ret;
	}

	stbuf->ops->set_wp(stbuf, (wp + len >= ep) ?
		stbuf->buf_start : (wp + len));

	if (stbuf->buf_wp == stbuf->buf_rp) {
		pr_debug("[%d]: stream buffer is full, payload: %d\n",
			stbuf->id, atomic_read(&stbuf->payload));
	}

	return len;
}

static int stream_buffer_write_inner(struct stream_buf_s *stbuf,
				     const u8 *in, u32 size)
{
	if (in == NULL || size > stbuf->buf_size) {
		pr_err("[%d]: params are not valid.\n", stbuf->id);
		return -1;
	}

	if (get_free_space(stbuf) < size)
		return -EAGAIN;

	return rb_push_data(stbuf, in, size);
}

static u32 stream_buffer_get_wp(struct stream_buf_s *stbuf)
{
	return stbuf->buf_wp;
}

static void stream_buffer_set_wp(struct stream_buf_s *stbuf, u32 val)
{
	int len = (val >= stbuf->buf_wp) ? (val - stbuf->buf_wp) :
		(stbuf->buf_size - stbuf->buf_wp + val);

	stbuf->buf_wp = val;
	vdec_set_vld_wp(container_of(stbuf, struct vdec_s, vbuf), stbuf->buf_wp);

	atomic_add(len, &stbuf->payload);
}

static u32 stream_buffer_get_rp(struct stream_buf_s *stbuf)
{
	return stbuf->buf_rp;
}

static void stream_buffer_set_rp(struct stream_buf_s *stbuf, u32 val)
{
	int len = (val >= stbuf->buf_rp) ? (val - stbuf->buf_rp) :
		(stbuf->buf_size - stbuf->buf_rp  + val);

	stbuf->buf_rp = val;
	atomic_sub(len, &stbuf->payload);
}

static struct stream_buf_ops stream_buffer_ops = {
	.init	= stream_buffer_init,
	.release = stream_buffer_release,
	.write	= stream_buffer_write_inner,
	.get_wp	= stream_buffer_get_wp,
	.set_wp	= stream_buffer_set_wp,
	.get_rp	= stream_buffer_get_rp,
	.set_rp	= stream_buffer_set_rp,
};

struct stream_buf_ops *get_stbuf_ops(void)
{
	return &stream_buffer_ops;
}
EXPORT_SYMBOL(get_stbuf_ops);

