/*
 * Samsung TV Mixer driver
 *
 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
 *
 * Tomasz Stanislawski, <t.stanislaws@samsung.com>
 *
 * 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 Foundiation. either version 2 of the License,
 * or (at your option) any later version
 */

#include "mixer.h"

#include "regs-vp.h"

#include <media/videobuf2-dma-contig.h>

/* FORMAT DEFINITIONS */
static const struct mxr_format mxr_fmt_nv12 = {
	.name = "NV12",
	.fourcc = V4L2_PIX_FMT_NV12,
	.colorspace = V4L2_COLORSPACE_JPEG,
	.num_planes = 2,
	.plane = {
		{ .width = 1, .height = 1, .size = 1 },
		{ .width = 2, .height = 2, .size = 2 },
	},
	.num_subframes = 1,
	.cookie = VP_MODE_NV12 | VP_MODE_MEM_LINEAR,
};

static const struct mxr_format mxr_fmt_nv21 = {
	.name = "NV21",
	.fourcc = V4L2_PIX_FMT_NV21,
	.colorspace = V4L2_COLORSPACE_JPEG,
	.num_planes = 2,
	.plane = {
		{ .width = 1, .height = 1, .size = 1 },
		{ .width = 2, .height = 2, .size = 2 },
	},
	.num_subframes = 1,
	.cookie = VP_MODE_NV21 | VP_MODE_MEM_LINEAR,
};

static const struct mxr_format mxr_fmt_nv12m = {
	.name = "NV12 (mplane)",
	.fourcc = V4L2_PIX_FMT_NV12M,
	.colorspace = V4L2_COLORSPACE_JPEG,
	.num_planes = 2,
	.plane = {
		{ .width = 1, .height = 1, .size = 1 },
		{ .width = 2, .height = 2, .size = 2 },
	},
	.num_subframes = 2,
	.plane2subframe = {0, 1},
	.cookie = VP_MODE_NV12 | VP_MODE_MEM_LINEAR,
};

static const struct mxr_format mxr_fmt_nv12mt = {
	.name = "NV12 tiled (mplane)",
	.fourcc = V4L2_PIX_FMT_NV12MT,
	.colorspace = V4L2_COLORSPACE_JPEG,
	.num_planes = 2,
	.plane = {
		{ .width = 128, .height = 32, .size = 4096 },
		{ .width = 128, .height = 32, .size = 2048 },
	},
	.num_subframes = 2,
	.plane2subframe = {0, 1},
	.cookie = VP_MODE_NV12 | VP_MODE_MEM_TILED,
};

static const struct mxr_format *mxr_video_format[] = {
	&mxr_fmt_nv12,
	&mxr_fmt_nv21,
	&mxr_fmt_nv12m,
	&mxr_fmt_nv12mt,
};

/* AUXILIARY CALLBACKS */

static void mxr_vp_layer_release(struct mxr_layer *layer)
{
	mxr_base_layer_unregister(layer);
	mxr_base_layer_release(layer);
}

static void mxr_vp_buffer_set(struct mxr_layer *layer,
	struct mxr_buffer *buf)
{
	dma_addr_t luma_addr[2] = {0, 0};
	dma_addr_t chroma_addr[2] = {0, 0};

	if (buf == NULL) {
		mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr);
		return;
	}
	luma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 0);
	if (layer->fmt->num_subframes == 2) {
		chroma_addr[0] = vb2_dma_contig_plane_dma_addr(&buf->vb, 1);
	} else {
		/* FIXME: mxr_get_plane_size compute integer division,
		 * which is slow and should not be performed in interrupt */
		chroma_addr[0] = luma_addr[0] + mxr_get_plane_size(
			&layer->fmt->plane[0], layer->geo.src.full_width,
			layer->geo.src.full_height);
	}
	if (layer->fmt->cookie & VP_MODE_MEM_TILED) {
		luma_addr[1] = luma_addr[0] + 0x40;
		chroma_addr[1] = chroma_addr[0] + 0x40;
	} else {
		luma_addr[1] = luma_addr[0] + layer->geo.src.full_width;
		chroma_addr[1] = chroma_addr[0];
	}
	mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr);
}

static void mxr_vp_stream_set(struct mxr_layer *layer, int en)
{
	mxr_reg_vp_layer_stream(layer->mdev, en);
}

static void mxr_vp_format_set(struct mxr_layer *layer)
{
	mxr_reg_vp_format(layer->mdev, layer->fmt, &layer->geo);
}

static inline unsigned int do_center(unsigned int center,
	unsigned int size, unsigned int upper, unsigned int flags)
{
	unsigned int lower;

	if (flags & MXR_NO_OFFSET)
		return 0;

	lower = center - min(center, size / 2);
	return min(lower, upper - size);
}

static void mxr_vp_fix_geometry(struct mxr_layer *layer,
	enum mxr_geometry_stage stage, unsigned long flags)
{
	struct mxr_geometry *geo = &layer->geo;
	struct mxr_crop *src = &geo->src;
	struct mxr_crop *dst = &geo->dst;
	unsigned long x_center, y_center;

	switch (stage) {

	case MXR_GEOMETRY_SINK: /* nothing to be fixed here */
	case MXR_GEOMETRY_COMPOSE:
		/* remember center of the area */
		x_center = dst->x_offset + dst->width / 2;
		y_center = dst->y_offset + dst->height / 2;

		/* ensure that compose is reachable using 16x scaling */
		dst->width = clamp(dst->width, 8U, 16 * src->full_width);
		dst->height = clamp(dst->height, 1U, 16 * src->full_height);

		/* setup offsets */
		dst->x_offset = do_center(x_center, dst->width,
			dst->full_width, flags);
		dst->y_offset = do_center(y_center, dst->height,
			dst->full_height, flags);
		flags = 0; /* remove possible MXR_NO_OFFSET flag */
		/* fall through */
	case MXR_GEOMETRY_CROP:
		/* remember center of the area */
		x_center = src->x_offset + src->width / 2;
		y_center = src->y_offset + src->height / 2;

		/* ensure scaling is between 0.25x .. 16x */
		src->width = clamp(src->width, round_up(dst->width / 16, 4),
			dst->width * 4);
		src->height = clamp(src->height, round_up(dst->height / 16, 4),
			dst->height * 4);

		/* hardware limits */
		src->width = clamp(src->width, 32U, 2047U);
		src->height = clamp(src->height, 4U, 2047U);

		/* setup offsets */
		src->x_offset = do_center(x_center, src->width,
			src->full_width, flags);
		src->y_offset = do_center(y_center, src->height,
			src->full_height, flags);

		/* setting scaling ratio */
		geo->x_ratio = (src->width << 16) / dst->width;
		geo->y_ratio = (src->height << 16) / dst->height;
		/* fall through */

	case MXR_GEOMETRY_SOURCE:
		src->full_width = clamp(src->full_width,
			ALIGN(src->width + src->x_offset, 8), 8192U);
		src->full_height = clamp(src->full_height,
			src->height + src->y_offset, 8192U);
	}
}

/* PUBLIC API */

struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx)
{
	struct mxr_layer *layer;
	int ret;
	struct mxr_layer_ops ops = {
		.release = mxr_vp_layer_release,
		.buffer_set = mxr_vp_buffer_set,
		.stream_set = mxr_vp_stream_set,
		.format_set = mxr_vp_format_set,
		.fix_geometry = mxr_vp_fix_geometry,
	};
	char name[32];

	sprintf(name, "video%d", idx);

	layer = mxr_base_layer_create(mdev, idx, name, &ops);
	if (layer == NULL) {
		mxr_err(mdev, "failed to initialize layer(%d) base\n", idx);
		goto fail;
	}

	layer->fmt_array = mxr_video_format;
	layer->fmt_array_size = ARRAY_SIZE(mxr_video_format);

	ret = mxr_base_layer_register(layer);
	if (ret)
		goto fail_layer;

	return layer;

fail_layer:
	mxr_base_layer_release(layer);

fail:
	return NULL;
}

