// SPDX-License-Identifier: GPL-2.0
/*
 * Driver for Renesas RZ/G2L CRU
 *
 * Copyright (C) 2022 Renesas Electronics Corp.
 */

#include "rzg2l-cru.h"

struct rzg2l_cru_ip_format {
	u32 code;
	unsigned int datatype;
	unsigned int bpp;
};

static const struct rzg2l_cru_ip_format rzg2l_cru_ip_formats[] = {
	{ .code = MEDIA_BUS_FMT_UYVY8_1X16,	.datatype = 0x1e, .bpp = 16 },
};

enum rzg2l_csi2_pads {
	RZG2L_CRU_IP_SINK = 0,
	RZG2L_CRU_IP_SOURCE,
};

static const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++)
		if (rzg2l_cru_ip_formats[i].code == code)
			return &rzg2l_cru_ip_formats[i];

	return NULL;
}

struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru)
{
	struct v4l2_subdev_state *state;
	struct v4l2_mbus_framefmt *fmt;

	state = v4l2_subdev_lock_and_get_active_state(&cru->ip.subdev);
	fmt = v4l2_subdev_state_get_format(state, 1);
	v4l2_subdev_unlock_state(state);

	return fmt;
}

static int rzg2l_cru_ip_s_stream(struct v4l2_subdev *sd, int enable)
{
	struct rzg2l_cru_dev *cru;
	int s_stream_ret = 0;
	int ret;

	cru = v4l2_get_subdevdata(sd);

	if (!enable) {
		ret = v4l2_subdev_call(cru->ip.remote, video, s_stream, enable);
		if (ret)
			s_stream_ret = ret;

		ret = v4l2_subdev_call(cru->ip.remote, video, post_streamoff);
		if (ret == -ENOIOCTLCMD)
			ret = 0;
		if (ret && !s_stream_ret)
			s_stream_ret = ret;
		rzg2l_cru_stop_image_processing(cru);
	} else {
		ret = v4l2_subdev_call(cru->ip.remote, video, pre_streamon, 0);
		if (ret == -ENOIOCTLCMD)
			ret = 0;
		if (ret)
			return ret;

		ret = rzg2l_cru_start_image_processing(cru);
		if (ret) {
			v4l2_subdev_call(cru->ip.remote, video, post_streamoff);
			return ret;
		}

		rzg2l_cru_vclk_unprepare(cru);

		ret = v4l2_subdev_call(cru->ip.remote, video, s_stream, enable);
		if (ret == -ENOIOCTLCMD)
			ret = 0;
		if (!ret) {
			ret = rzg2l_cru_vclk_prepare(cru);
			if (!ret)
				return 0;
		} else {
			/* enable back vclk so that s_stream in error path disables it */
			if (rzg2l_cru_vclk_prepare(cru))
				dev_err(cru->dev, "Failed to enable vclk\n");
		}

		s_stream_ret = ret;

		v4l2_subdev_call(cru->ip.remote, video, post_streamoff);
		rzg2l_cru_stop_image_processing(cru);
	}

	return s_stream_ret;
}

static int rzg2l_cru_ip_set_format(struct v4l2_subdev *sd,
				   struct v4l2_subdev_state *state,
				   struct v4l2_subdev_format *fmt)
{
	struct v4l2_mbus_framefmt *src_format;
	struct v4l2_mbus_framefmt *sink_format;

	src_format = v4l2_subdev_state_get_format(state, RZG2L_CRU_IP_SOURCE);
	if (fmt->pad == RZG2L_CRU_IP_SOURCE) {
		fmt->format = *src_format;
		return 0;
	}

	sink_format = v4l2_subdev_state_get_format(state, fmt->pad);

	if (!rzg2l_cru_ip_code_to_fmt(fmt->format.code))
		sink_format->code = rzg2l_cru_ip_formats[0].code;
	else
		sink_format->code = fmt->format.code;

	sink_format->field = V4L2_FIELD_NONE;
	sink_format->colorspace = fmt->format.colorspace;
	sink_format->xfer_func = fmt->format.xfer_func;
	sink_format->ycbcr_enc = fmt->format.ycbcr_enc;
	sink_format->quantization = fmt->format.quantization;
	sink_format->width = clamp_t(u32, fmt->format.width,
				     RZG2L_CRU_MIN_INPUT_WIDTH, RZG2L_CRU_MAX_INPUT_WIDTH);
	sink_format->height = clamp_t(u32, fmt->format.height,
				      RZG2L_CRU_MIN_INPUT_HEIGHT, RZG2L_CRU_MAX_INPUT_HEIGHT);

	fmt->format = *sink_format;

	/* propagate format to source pad */
	*src_format = *sink_format;

	return 0;
}

static int rzg2l_cru_ip_enum_mbus_code(struct v4l2_subdev *sd,
				       struct v4l2_subdev_state *state,
				       struct v4l2_subdev_mbus_code_enum *code)
{
	if (code->index >= ARRAY_SIZE(rzg2l_cru_ip_formats))
		return -EINVAL;

	code->code = rzg2l_cru_ip_formats[code->index].code;
	return 0;
}

static int rzg2l_cru_ip_enum_frame_size(struct v4l2_subdev *sd,
					struct v4l2_subdev_state *state,
					struct v4l2_subdev_frame_size_enum *fse)
{
	if (fse->index != 0)
		return -EINVAL;

	if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16)
		return -EINVAL;

	fse->min_width = RZG2L_CRU_MIN_INPUT_WIDTH;
	fse->min_height = RZG2L_CRU_MIN_INPUT_HEIGHT;
	fse->max_width = RZG2L_CRU_MAX_INPUT_WIDTH;
	fse->max_height = RZG2L_CRU_MAX_INPUT_HEIGHT;

	return 0;
}

static int rzg2l_cru_ip_init_state(struct v4l2_subdev *sd,
				   struct v4l2_subdev_state *sd_state)
{
	struct v4l2_subdev_format fmt = { .pad = RZG2L_CRU_IP_SINK, };

	fmt.format.width = RZG2L_CRU_MIN_INPUT_WIDTH;
	fmt.format.height = RZG2L_CRU_MIN_INPUT_HEIGHT;
	fmt.format.field = V4L2_FIELD_NONE;
	fmt.format.code = MEDIA_BUS_FMT_UYVY8_1X16;
	fmt.format.colorspace = V4L2_COLORSPACE_SRGB;
	fmt.format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
	fmt.format.quantization = V4L2_QUANTIZATION_DEFAULT;
	fmt.format.xfer_func = V4L2_XFER_FUNC_DEFAULT;

	return rzg2l_cru_ip_set_format(sd, sd_state, &fmt);
}

static const struct v4l2_subdev_video_ops rzg2l_cru_ip_video_ops = {
	.s_stream = rzg2l_cru_ip_s_stream,
};

static const struct v4l2_subdev_pad_ops rzg2l_cru_ip_pad_ops = {
	.enum_mbus_code = rzg2l_cru_ip_enum_mbus_code,
	.enum_frame_size = rzg2l_cru_ip_enum_frame_size,
	.get_fmt = v4l2_subdev_get_fmt,
	.set_fmt = rzg2l_cru_ip_set_format,
};

static const struct v4l2_subdev_ops rzg2l_cru_ip_subdev_ops = {
	.video = &rzg2l_cru_ip_video_ops,
	.pad = &rzg2l_cru_ip_pad_ops,
};

static const struct v4l2_subdev_internal_ops rzg2l_cru_ip_internal_ops = {
	.init_state = rzg2l_cru_ip_init_state,
};

static const struct media_entity_operations rzg2l_cru_ip_entity_ops = {
	.link_validate = v4l2_subdev_link_validate,
};

int rzg2l_cru_ip_subdev_register(struct rzg2l_cru_dev *cru)
{
	struct rzg2l_cru_ip *ip = &cru->ip;
	int ret;

	ip->subdev.dev = cru->dev;
	v4l2_subdev_init(&ip->subdev, &rzg2l_cru_ip_subdev_ops);
	ip->subdev.internal_ops = &rzg2l_cru_ip_internal_ops;
	v4l2_set_subdevdata(&ip->subdev, cru);
	snprintf(ip->subdev.name, sizeof(ip->subdev.name),
		 "cru-ip-%s", dev_name(cru->dev));
	ip->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;

	ip->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
	ip->subdev.entity.ops = &rzg2l_cru_ip_entity_ops;

	ip->pads[0].flags = MEDIA_PAD_FL_SINK;
	ip->pads[1].flags = MEDIA_PAD_FL_SOURCE;

	ret = media_entity_pads_init(&ip->subdev.entity, 2, ip->pads);
	if (ret)
		return ret;

	ret = v4l2_subdev_init_finalize(&ip->subdev);
	if (ret < 0)
		goto entity_cleanup;

	ret = v4l2_device_register_subdev(&cru->v4l2_dev, &ip->subdev);
	if (ret < 0)
		goto error_subdev;

	return 0;
error_subdev:
	v4l2_subdev_cleanup(&ip->subdev);
entity_cleanup:
	media_entity_cleanup(&ip->subdev.entity);

	return ret;
}

void rzg2l_cru_ip_subdev_unregister(struct rzg2l_cru_dev *cru)
{
	struct rzg2l_cru_ip *ip = &cru->ip;

	media_entity_cleanup(&ip->subdev.entity);
	v4l2_subdev_cleanup(&ip->subdev);
	v4l2_device_unregister_subdev(&ip->subdev);
}
