/*
 * vsp1_wpf.c  --  R-Car VSP1 Write Pixel Formatter
 *
 * Copyright (C) 2013-2014 Renesas Electronics Corporation
 *
 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.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 Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/device.h>

#include <media/v4l2-subdev.h>

#include "vsp1.h"
#include "vsp1_dl.h"
#include "vsp1_pipe.h"
#include "vsp1_rwpf.h"
#include "vsp1_video.h"

#define WPF_GEN2_MAX_WIDTH			2048U
#define WPF_GEN2_MAX_HEIGHT			2048U
#define WPF_GEN3_MAX_WIDTH			8190U
#define WPF_GEN3_MAX_HEIGHT			8190U

/* -----------------------------------------------------------------------------
 * Device Access
 */

static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf,
				  struct vsp1_dl_list *dl, u32 reg, u32 data)
{
	vsp1_dl_list_write(dl, reg + wpf->entity.index * VI6_WPF_OFFSET, data);
}

/* -----------------------------------------------------------------------------
 * Controls
 */

enum wpf_flip_ctrl {
	WPF_CTRL_VFLIP = 0,
	WPF_CTRL_HFLIP = 1,
};

static int vsp1_wpf_set_rotation(struct vsp1_rwpf *wpf, unsigned int rotation)
{
	struct vsp1_video *video = wpf->video;
	struct v4l2_mbus_framefmt *sink_format;
	struct v4l2_mbus_framefmt *source_format;
	bool rotate;
	int ret = 0;

	/*
	 * Only consider the 0°/180° from/to 90°/270° modifications, the rest
	 * is taken care of by the flipping configuration.
	 */
	rotate = rotation == 90 || rotation == 270;
	if (rotate == wpf->flip.rotate)
		return 0;

	/* Changing rotation isn't allowed when buffers are allocated. */
	mutex_lock(&video->lock);

	if (vb2_is_busy(&video->queue)) {
		ret = -EBUSY;
		goto done;
	}

	sink_format = vsp1_entity_get_pad_format(&wpf->entity,
						 wpf->entity.config,
						 RWPF_PAD_SINK);
	source_format = vsp1_entity_get_pad_format(&wpf->entity,
						   wpf->entity.config,
						   RWPF_PAD_SOURCE);

	mutex_lock(&wpf->entity.lock);

	if (rotate) {
		source_format->width = sink_format->height;
		source_format->height = sink_format->width;
	} else {
		source_format->width = sink_format->width;
		source_format->height = sink_format->height;
	}

	wpf->flip.rotate = rotate;

	mutex_unlock(&wpf->entity.lock);

done:
	mutex_unlock(&video->lock);
	return ret;
}

static int vsp1_wpf_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct vsp1_rwpf *wpf =
		container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
	unsigned int rotation;
	u32 flip = 0;
	int ret;

	/* Update the rotation. */
	rotation = wpf->flip.ctrls.rotate ? wpf->flip.ctrls.rotate->val : 0;
	ret = vsp1_wpf_set_rotation(wpf, rotation);
	if (ret < 0)
		return ret;

	/*
	 * Compute the flip value resulting from all three controls, with
	 * rotation by 180° flipping the image in both directions. Store the
	 * result in the pending flip field for the next frame that will be
	 * processed.
	 */
	if (wpf->flip.ctrls.vflip->val)
		flip |= BIT(WPF_CTRL_VFLIP);

	if (wpf->flip.ctrls.hflip && wpf->flip.ctrls.hflip->val)
		flip |= BIT(WPF_CTRL_HFLIP);

	if (rotation == 180 || rotation == 270)
		flip ^= BIT(WPF_CTRL_VFLIP) | BIT(WPF_CTRL_HFLIP);

	spin_lock_irq(&wpf->flip.lock);
	wpf->flip.pending = flip;
	spin_unlock_irq(&wpf->flip.lock);

	return 0;
}

static const struct v4l2_ctrl_ops vsp1_wpf_ctrl_ops = {
	.s_ctrl = vsp1_wpf_s_ctrl,
};

static int wpf_init_controls(struct vsp1_rwpf *wpf)
{
	struct vsp1_device *vsp1 = wpf->entity.vsp1;
	unsigned int num_flip_ctrls;

	spin_lock_init(&wpf->flip.lock);

	if (wpf->entity.index != 0) {
		/* Only WPF0 supports flipping. */
		num_flip_ctrls = 0;
	} else if (vsp1->info->features & VSP1_HAS_WPF_HFLIP) {
		/*
		 * When horizontal flip is supported the WPF implements three
		 * controls (horizontal flip, vertical flip and rotation).
		 */
		num_flip_ctrls = 3;
	} else if (vsp1->info->features & VSP1_HAS_WPF_VFLIP) {
		/*
		 * When only vertical flip is supported the WPF implements a
		 * single control (vertical flip).
		 */
		num_flip_ctrls = 1;
	} else {
		/* Otherwise flipping is not supported. */
		num_flip_ctrls = 0;
	}

	vsp1_rwpf_init_ctrls(wpf, num_flip_ctrls);

	if (num_flip_ctrls >= 1) {
		wpf->flip.ctrls.vflip =
			v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops,
					  V4L2_CID_VFLIP, 0, 1, 1, 0);
	}

	if (num_flip_ctrls == 3) {
		wpf->flip.ctrls.hflip =
			v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops,
					  V4L2_CID_HFLIP, 0, 1, 1, 0);
		wpf->flip.ctrls.rotate =
			v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops,
					  V4L2_CID_ROTATE, 0, 270, 90, 0);
		v4l2_ctrl_cluster(3, &wpf->flip.ctrls.vflip);
	}

	if (wpf->ctrls.error) {
		dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
			wpf->entity.index);
		return wpf->ctrls.error;
	}

	return 0;
}

/* -----------------------------------------------------------------------------
 * V4L2 Subdevice Core Operations
 */

static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
{
	struct vsp1_rwpf *wpf = to_rwpf(subdev);
	struct vsp1_device *vsp1 = wpf->entity.vsp1;

	if (enable)
		return 0;

	/*
	 * Write to registers directly when stopping the stream as there will be
	 * no pipeline run to apply the display list.
	 */
	vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0);
	vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET +
		   VI6_WPF_SRCRPF, 0);

	return 0;
}

/* -----------------------------------------------------------------------------
 * V4L2 Subdevice Operations
 */

static const struct v4l2_subdev_video_ops wpf_video_ops = {
	.s_stream = wpf_s_stream,
};

static const struct v4l2_subdev_ops wpf_ops = {
	.video	= &wpf_video_ops,
	.pad    = &vsp1_rwpf_pad_ops,
};

/* -----------------------------------------------------------------------------
 * VSP1 Entity Operations
 */

static void vsp1_wpf_destroy(struct vsp1_entity *entity)
{
	struct vsp1_rwpf *wpf = entity_to_rwpf(entity);

	vsp1_dlm_destroy(wpf->dlm);
}

static void wpf_configure(struct vsp1_entity *entity,
			  struct vsp1_pipeline *pipe,
			  struct vsp1_dl_list *dl,
			  enum vsp1_entity_params params)
{
	struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);
	struct vsp1_device *vsp1 = wpf->entity.vsp1;
	const struct v4l2_mbus_framefmt *source_format;
	const struct v4l2_mbus_framefmt *sink_format;
	unsigned int i;
	u32 outfmt = 0;
	u32 srcrpf = 0;

	if (params == VSP1_ENTITY_PARAMS_RUNTIME) {
		const unsigned int mask = BIT(WPF_CTRL_VFLIP)
					| BIT(WPF_CTRL_HFLIP);
		unsigned long flags;

		spin_lock_irqsave(&wpf->flip.lock, flags);
		wpf->flip.active = (wpf->flip.active & ~mask)
				 | (wpf->flip.pending & mask);
		spin_unlock_irqrestore(&wpf->flip.lock, flags);

		outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt;

		if (wpf->flip.active & BIT(WPF_CTRL_VFLIP))
			outfmt |= VI6_WPF_OUTFMT_FLP;
		if (wpf->flip.active & BIT(WPF_CTRL_HFLIP))
			outfmt |= VI6_WPF_OUTFMT_HFLP;

		vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt);
		return;
	}

	sink_format = vsp1_entity_get_pad_format(&wpf->entity,
						 wpf->entity.config,
						 RWPF_PAD_SINK);
	source_format = vsp1_entity_get_pad_format(&wpf->entity,
						   wpf->entity.config,
						   RWPF_PAD_SOURCE);

	if (params == VSP1_ENTITY_PARAMS_PARTITION) {
		const struct v4l2_pix_format_mplane *format = &wpf->format;
		const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
		struct vsp1_rwpf_memory mem = wpf->mem;
		unsigned int flip = wpf->flip.active;
		unsigned int width = sink_format->width;
		unsigned int height = sink_format->height;
		unsigned int offset;

		/*
		 * Cropping. The partition algorithm can split the image into
		 * multiple slices.
		 */
		if (pipe->partitions > 1)
			width = pipe->partition.width;

		vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN |
			       (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
			       (width << VI6_WPF_SZCLIP_SIZE_SHIFT));
		vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN |
			       (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
			       (height << VI6_WPF_SZCLIP_SIZE_SHIFT));

		if (pipe->lif)
			return;

		/*
		 * Update the memory offsets based on flipping configuration.
		 * The destination addresses point to the locations where the
		 * VSP starts writing to memory, which can be any corner of the
		 * image depending on the combination of flipping and rotation.
		 */

		/*
		 * First take the partition left coordinate into account.
		 * Compute the offset to order the partitions correctly on the
		 * output based on whether flipping is enabled. Consider
		 * horizontal flipping when rotation is disabled but vertical
		 * flipping when rotation is enabled, as rotating the image
		 * switches the horizontal and vertical directions. The offset
		 * is applied horizontally or vertically accordingly.
		 */
		if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate)
			offset = format->width - pipe->partition.left
				- pipe->partition.width;
		else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate)
			offset = format->height - pipe->partition.left
				- pipe->partition.width;
		else
			offset = pipe->partition.left;

		for (i = 0; i < format->num_planes; ++i) {
			unsigned int hsub = i > 0 ? fmtinfo->hsub : 1;
			unsigned int vsub = i > 0 ? fmtinfo->vsub : 1;

			if (wpf->flip.rotate)
				mem.addr[i] += offset / vsub
					     * format->plane_fmt[i].bytesperline;
			else
				mem.addr[i] += offset / hsub
					     * fmtinfo->bpp[i] / 8;
		}

		if (flip & BIT(WPF_CTRL_VFLIP)) {
			/*
			 * When rotating the output (after rotation) image
			 * height is equal to the partition width (before
			 * rotation). Otherwise it is equal to the output
			 * image height.
			 */
			if (wpf->flip.rotate)
				height = pipe->partition.width;
			else
				height = format->height;

			mem.addr[0] += (height - 1)
				     * format->plane_fmt[0].bytesperline;

			if (format->num_planes > 1) {
				offset = (height / fmtinfo->vsub - 1)
				       * format->plane_fmt[1].bytesperline;
				mem.addr[1] += offset;
				mem.addr[2] += offset;
			}
		}

		if (wpf->flip.rotate && !(flip & BIT(WPF_CTRL_HFLIP))) {
			unsigned int hoffset = max(0, (int)format->width - 16);

			/*
			 * Compute the output coordinate. The partition
			 * horizontal (left) offset becomes a vertical offset.
			 */
			for (i = 0; i < format->num_planes; ++i) {
				unsigned int hsub = i > 0 ? fmtinfo->hsub : 1;

				mem.addr[i] += hoffset / hsub
					     * fmtinfo->bpp[i] / 8;
			}
		}

		/*
		 * On Gen3 hardware the SPUVS bit has no effect on 3-planar
		 * formats. Swap the U and V planes manually in that case.
		 */
		if (vsp1->info->gen == 3 && format->num_planes == 3 &&
		    fmtinfo->swap_uv)
			swap(mem.addr[1], mem.addr[2]);

		vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]);
		vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]);
		vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]);
		return;
	}

	/* Format */
	if (!pipe->lif) {
		const struct v4l2_pix_format_mplane *format = &wpf->format;
		const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;

		outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT;

		if (wpf->flip.rotate)
			outfmt |= VI6_WPF_OUTFMT_ROT;

		if (fmtinfo->alpha)
			outfmt |= VI6_WPF_OUTFMT_PXA;
		if (fmtinfo->swap_yc)
			outfmt |= VI6_WPF_OUTFMT_SPYCS;
		if (fmtinfo->swap_uv)
			outfmt |= VI6_WPF_OUTFMT_SPUVS;

		/* Destination stride and byte swapping. */
		vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_STRIDE_Y,
			       format->plane_fmt[0].bytesperline);
		if (format->num_planes > 1)
			vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_STRIDE_C,
				       format->plane_fmt[1].bytesperline);

		vsp1_wpf_write(wpf, dl, VI6_WPF_DSWAP, fmtinfo->swap);

		if (vsp1->info->features & VSP1_HAS_WPF_HFLIP &&
		    wpf->entity.index == 0)
			vsp1_wpf_write(wpf, dl, VI6_WPF_ROT_CTRL,
				       VI6_WPF_ROT_CTRL_LN16 |
				       (256 << VI6_WPF_ROT_CTRL_LMEM_WD_SHIFT));
	}

	if (sink_format->code != source_format->code)
		outfmt |= VI6_WPF_OUTFMT_CSC;

	wpf->outfmt = outfmt;

	vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index),
			   VI6_DPR_WPF_FPORCH_FP_WPFN);

	vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);

	/*
	 * Sources. If the pipeline has a single input and BRU is not used,
	 * configure it as the master layer. Otherwise configure all
	 * inputs as sub-layers and select the virtual RPF as the master
	 * layer.
	 */
	for (i = 0; i < vsp1->info->rpf_count; ++i) {
		struct vsp1_rwpf *input = pipe->inputs[i];

		if (!input)
			continue;

		srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
			? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
			: VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
	}

	if (pipe->bru || pipe->num_inputs > 1)
		srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST;

	vsp1_wpf_write(wpf, dl, VI6_WPF_SRCRPF, srcrpf);

	/* Enable interrupts */
	vsp1_dl_list_write(dl, VI6_WPF_IRQ_STA(wpf->entity.index), 0);
	vsp1_dl_list_write(dl, VI6_WPF_IRQ_ENB(wpf->entity.index),
			   VI6_WFP_IRQ_ENB_DFEE);
}

static unsigned int wpf_max_width(struct vsp1_entity *entity,
				  struct vsp1_pipeline *pipe)
{
	struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);

	return wpf->flip.rotate ? 256 : wpf->max_width;
}

static const struct vsp1_entity_operations wpf_entity_ops = {
	.destroy = vsp1_wpf_destroy,
	.configure = wpf_configure,
	.max_width = wpf_max_width,
};

/* -----------------------------------------------------------------------------
 * Initialization and Cleanup
 */

struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
{
	struct vsp1_rwpf *wpf;
	char name[6];
	int ret;

	wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL);
	if (wpf == NULL)
		return ERR_PTR(-ENOMEM);

	if (vsp1->info->gen == 2) {
		wpf->max_width = WPF_GEN2_MAX_WIDTH;
		wpf->max_height = WPF_GEN2_MAX_HEIGHT;
	} else {
		wpf->max_width = WPF_GEN3_MAX_WIDTH;
		wpf->max_height = WPF_GEN3_MAX_HEIGHT;
	}

	wpf->entity.ops = &wpf_entity_ops;
	wpf->entity.type = VSP1_ENTITY_WPF;
	wpf->entity.index = index;

	sprintf(name, "wpf.%u", index);
	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops,
			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
	if (ret < 0)
		return ERR_PTR(ret);

	/* Initialize the display list manager. */
	wpf->dlm = vsp1_dlm_create(vsp1, index, 64);
	if (!wpf->dlm) {
		ret = -ENOMEM;
		goto error;
	}

	/* Initialize the control handler. */
	ret = wpf_init_controls(wpf);
	if (ret < 0) {
		dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
			index);
		goto error;
	}

	v4l2_ctrl_handler_setup(&wpf->ctrls);

	return wpf;

error:
	vsp1_entity_destroy(&wpf->entity);
	return ERR_PTR(ret);
}
