/*
 * Copyright (c) 2015-2016 MediaTek Inc.
 * Author: Houlong Wei <houlong.wei@mediatek.com>
 *         Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * 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.
 */

#include <linux/platform_device.h>

#include "mtk_mdp_core.h"
#include "mtk_mdp_regs.h"
#include "mtk_mdp_type.h"

static int32_t mtk_mdp_map_color_format(int v4l2_format)
{
	switch (v4l2_format) {
	case V4L2_PIX_FMT_NV12M:
	case V4L2_PIX_FMT_NV12:
		return DP_COLOR_NV12;
	case V4L2_PIX_FMT_NV21M:
	case V4L2_PIX_FMT_NV21:
		return DP_COLOR_NV21;
	case V4L2_PIX_FMT_MT21C:
		return DP_COLOR_420_BLKP_UFO;
	case V4L2_PIX_FMT_MT21:
		return DP_COLOR_420_BLKP;
	case V4L2_PIX_FMT_YUV420M:
	case V4L2_PIX_FMT_YUV420:
		return DP_COLOR_I420;
	case V4L2_PIX_FMT_YVU420M:
	case V4L2_PIX_FMT_YVU420:
		return DP_COLOR_YV12;
	case V4L2_PIX_FMT_YUV422P:
		return DP_COLOR_I422;
	case V4L2_PIX_FMT_NV16:
	case V4L2_PIX_FMT_NV16M:
		return DP_COLOR_NV16;
	case V4L2_PIX_FMT_YUYV:
		return DP_COLOR_YUYV;
	case V4L2_PIX_FMT_UYVY:
		return DP_COLOR_UYVY;
	case V4L2_PIX_FMT_YVYU:
		return DP_COLOR_YVYU;
	case V4L2_PIX_FMT_VYUY:
		return DP_COLOR_VYUY;
	case V4L2_PIX_FMT_ARGB32:
		return DP_COLOR_RGBA8888;
	case V4L2_PIX_FMT_ABGR32:
		return DP_COLOR_BGRA8888;
	case V4L2_PIX_FMT_XRGB32:
		return DP_COLOR_RGBA8888;
	case V4L2_PIX_FMT_XBGR32:
		return DP_COLOR_BGRA8888;
	case V4L2_PIX_FMT_RGB565:
		return DP_COLOR_RGB565;
	case V4L2_PIX_FMT_RGB24:
		return DP_COLOR_RGB888;
	case V4L2_PIX_FMT_BGR24:
		return DP_COLOR_BGR888;
	}

	mtk_mdp_err("Unknown format 0x%x", v4l2_format);

	return DP_COLOR_UNKNOWN;
}

void mtk_mdp_hw_set_input_addr(struct mtk_mdp_ctx *ctx,
			       struct mtk_mdp_addr *addr)
{
	struct mdp_buffer *src_buf = &ctx->vpu.vsi->src_buffer;
	int i;

	for (i = 0; i < ARRAY_SIZE(addr->addr); i++)
		src_buf->addr_mva[i] = (uint64_t)addr->addr[i];
}

void mtk_mdp_hw_set_output_addr(struct mtk_mdp_ctx *ctx,
				struct mtk_mdp_addr *addr)
{
	struct mdp_buffer *dst_buf = &ctx->vpu.vsi->dst_buffer;
	int i;

	for (i = 0; i < ARRAY_SIZE(addr->addr); i++)
		dst_buf->addr_mva[i] = (uint64_t)addr->addr[i];
}

void mtk_mdp_hw_set_in_size(struct mtk_mdp_ctx *ctx)
{
	struct mtk_mdp_frame *frame = &ctx->s_frame;
	struct mdp_config *config = &ctx->vpu.vsi->src_config;

	/* Set input pixel offset */
	config->crop_x = frame->crop.left;
	config->crop_y = frame->crop.top;

	/* Set input cropped size */
	config->crop_w = frame->crop.width;
	config->crop_h = frame->crop.height;

	/* Set input original size */
	config->x = 0;
	config->y = 0;
	config->w = frame->width;
	config->h = frame->height;
}

void mtk_mdp_hw_set_in_image_format(struct mtk_mdp_ctx *ctx)
{
	unsigned int i, num_comp;
	struct mtk_mdp_frame *frame = &ctx->s_frame;
	struct mdp_config *config = &ctx->vpu.vsi->src_config;
	struct mdp_buffer *src_buf = &ctx->vpu.vsi->src_buffer;

	num_comp = frame->fmt->num_comp;
	src_buf->plane_num = num_comp;
	config->format = mtk_mdp_map_color_format(frame->fmt->pixelformat);
	if (frame->fmt->num_planes == 1 && num_comp > 1) {
		config->pitch[0] = frame->pitch[0];
		config->pitch[1] = frame->pitch[1];
		config->pitch[2] = frame->pitch[2];
		src_buf->plane_size[0] =
			(int32_t)(frame->addr.addr[1] - frame->addr.addr[0]);
		if (num_comp > 2) {
			src_buf->plane_size[1] =
				(int32_t)(frame->addr.addr[2] -
				frame->addr.addr[1]);
			src_buf->plane_size[2] = frame->payload[0] -
				src_buf->plane_size[0] -
				src_buf->plane_size[1];
		} else
			src_buf->plane_size[1] = frame->payload[0] -
				src_buf->plane_size[0];
	} else {
		for (i = 0; i < src_buf->plane_num; i++) {
			config->pitch[i] = frame->pitch[i];
			src_buf->plane_size[i] = (int32_t)frame->payload[i];
		}
	}
}

void mtk_mdp_hw_set_out_size(struct mtk_mdp_ctx *ctx)
{
	struct mtk_mdp_frame *frame = &ctx->d_frame;
	struct mdp_config *config = &ctx->vpu.vsi->dst_config;

	config->crop_x = frame->crop.left;
	config->crop_y = frame->crop.top;
	config->crop_w = frame->crop.width;
	config->crop_h = frame->crop.height;
	config->x = 0;
	config->y = 0;
	config->w = frame->width;
	config->h = frame->height;
}

void mtk_mdp_hw_set_out_image_format(struct mtk_mdp_ctx *ctx)
{
	unsigned int i, num_comp;
	struct mtk_mdp_frame *frame = &ctx->d_frame;
	struct mdp_config *config = &ctx->vpu.vsi->dst_config;
	struct mdp_buffer *dst_buf = &ctx->vpu.vsi->dst_buffer;

	num_comp = frame->fmt->num_comp;
	dst_buf->plane_num = num_comp;
	config->format = mtk_mdp_map_color_format(frame->fmt->pixelformat);
	if (frame->fmt->num_planes == 1 && num_comp > 1) {
		config->pitch[0] = frame->pitch[0];
		config->pitch[1] = frame->pitch[1];
		config->pitch[2] = frame->pitch[2];
		dst_buf->plane_size[0] =
			(int32_t)(frame->addr.addr[1] - frame->addr.addr[0]);
		if (num_comp > 2) {
			dst_buf->plane_size[1] =
				(int32_t)(frame->addr.addr[2] -
				frame->addr.addr[1]);
			dst_buf->plane_size[2] = frame->payload[0] -
				dst_buf->plane_size[0] -
				dst_buf->plane_size[1];
		} else
			dst_buf->plane_size[1] = frame->payload[0] -
				dst_buf->plane_size[0];
	} else {
		for (i = 0; i < dst_buf->plane_num; i++) {
			config->pitch[i] = frame->pitch[i];
			dst_buf->plane_size[i] = (int32_t)frame->payload[i];
		}
	}
}

void mtk_mdp_hw_set_rotation(struct mtk_mdp_ctx *ctx)
{
	struct mdp_config_misc *misc = &ctx->vpu.vsi->misc;

	misc->orientation = ctx->ctrls.rotate->val;
	misc->hflip = ctx->ctrls.hflip->val;
	misc->vflip = ctx->ctrls.vflip->val;
}

void mtk_mdp_hw_set_global_alpha(struct mtk_mdp_ctx *ctx)
{
	struct mdp_config_misc *misc = &ctx->vpu.vsi->misc;

	misc->alpha = ctx->ctrls.global_alpha->val;
}

void mtk_mdp_hw_set_pq_info(struct mtk_mdp_ctx *ctx)
{
	struct mdp_pq_info *vsi_pq = &ctx->vpu.vsi->pq;

	vsi_pq->sharpness_enable = !!ctx->sharpness;
	vsi_pq->sharpness_level = ctx->sharpness;
	vsi_pq->dynamic_contrast_enable = ctx->contrast_auto;
}
