// SPDX-License-Identifier: GPL-2.0
/*
 * R-Car Display Unit Writeback Support
 *
 * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 */

#include <drm/drm_atomic_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_writeback.h>

#include "rcar_du_crtc.h"
#include "rcar_du_drv.h"
#include "rcar_du_kms.h"
#include "rcar_du_writeback.h"

/**
 * struct rcar_du_wb_conn_state - Driver-specific writeback connector state
 * @state: base DRM connector state
 * @format: format of the writeback framebuffer
 */
struct rcar_du_wb_conn_state {
	struct drm_connector_state state;
	const struct rcar_du_format_info *format;
};

#define to_rcar_wb_conn_state(s) \
	container_of(s, struct rcar_du_wb_conn_state, state)

/**
 * struct rcar_du_wb_job - Driver-private data for writeback jobs
 * @sg_tables: scatter-gather tables for the framebuffer memory
 */
struct rcar_du_wb_job {
	struct sg_table sg_tables[3];
};

static int rcar_du_wb_conn_get_modes(struct drm_connector *connector)
{
	struct drm_device *dev = connector->dev;

	return drm_add_modes_noedid(connector, dev->mode_config.max_width,
				    dev->mode_config.max_height);
}

static int rcar_du_wb_prepare_job(struct drm_writeback_connector *connector,
				  struct drm_writeback_job *job)
{
	struct rcar_du_crtc *rcrtc = wb_to_rcar_crtc(connector);
	struct rcar_du_wb_job *rjob;
	int ret;

	if (!job->fb)
		return 0;

	rjob = kzalloc(sizeof(*rjob), GFP_KERNEL);
	if (!rjob)
		return -ENOMEM;

	/* Map the framebuffer to the VSP. */
	ret = rcar_du_vsp_map_fb(rcrtc->vsp, job->fb, rjob->sg_tables);
	if (ret < 0) {
		kfree(rjob);
		return ret;
	}

	job->priv = rjob;
	return 0;
}

static void rcar_du_wb_cleanup_job(struct drm_writeback_connector *connector,
				   struct drm_writeback_job *job)
{
	struct rcar_du_crtc *rcrtc = wb_to_rcar_crtc(connector);
	struct rcar_du_wb_job *rjob = job->priv;

	if (!job->fb)
		return;

	rcar_du_vsp_unmap_fb(rcrtc->vsp, job->fb, rjob->sg_tables);
	kfree(rjob);
}

static const struct drm_connector_helper_funcs rcar_du_wb_conn_helper_funcs = {
	.get_modes = rcar_du_wb_conn_get_modes,
	.prepare_writeback_job = rcar_du_wb_prepare_job,
	.cleanup_writeback_job = rcar_du_wb_cleanup_job,
};

static struct drm_connector_state *
rcar_du_wb_conn_duplicate_state(struct drm_connector *connector)
{
	struct rcar_du_wb_conn_state *copy;

	if (WARN_ON(!connector->state))
		return NULL;

	copy = kzalloc(sizeof(*copy), GFP_KERNEL);
	if (!copy)
		return NULL;

	__drm_atomic_helper_connector_duplicate_state(connector, &copy->state);

	return &copy->state;
}

static void rcar_du_wb_conn_destroy_state(struct drm_connector *connector,
					  struct drm_connector_state *state)
{
	__drm_atomic_helper_connector_destroy_state(state);
	kfree(to_rcar_wb_conn_state(state));
}

static void rcar_du_wb_conn_reset(struct drm_connector *connector)
{
	struct rcar_du_wb_conn_state *state;

	if (connector->state) {
		rcar_du_wb_conn_destroy_state(connector, connector->state);
		connector->state = NULL;
	}

	state = kzalloc(sizeof(*state), GFP_KERNEL);
	if (state == NULL)
		return;

	__drm_atomic_helper_connector_reset(connector, &state->state);
}

static const struct drm_connector_funcs rcar_du_wb_conn_funcs = {
	.reset = rcar_du_wb_conn_reset,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.destroy = drm_connector_cleanup,
	.atomic_duplicate_state = rcar_du_wb_conn_duplicate_state,
	.atomic_destroy_state = rcar_du_wb_conn_destroy_state,
};

static int rcar_du_wb_enc_atomic_check(struct drm_encoder *encoder,
				       struct drm_crtc_state *crtc_state,
				       struct drm_connector_state *conn_state)
{
	struct rcar_du_wb_conn_state *wb_state =
		to_rcar_wb_conn_state(conn_state);
	const struct drm_display_mode *mode = &crtc_state->mode;
	struct drm_device *dev = encoder->dev;
	struct drm_framebuffer *fb;

	if (!conn_state->writeback_job)
		return 0;

	fb = conn_state->writeback_job->fb;

	/*
	 * Verify that the framebuffer format is supported and that its size
	 * matches the current mode.
	 */
	if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) {
		dev_dbg(dev->dev, "%s: invalid framebuffer size %ux%u\n",
			__func__, fb->width, fb->height);
		return -EINVAL;
	}

	wb_state->format = rcar_du_format_info(fb->format->format);
	if (wb_state->format == NULL) {
		dev_dbg(dev->dev, "%s: unsupported format %p4cc\n", __func__,
			&fb->format->format);
		return -EINVAL;
	}

	return 0;
}

static const struct drm_encoder_helper_funcs rcar_du_wb_enc_helper_funcs = {
	.atomic_check = rcar_du_wb_enc_atomic_check,
};

/*
 * Only RGB formats are currently supported as the VSP outputs RGB to the DU
 * and can't convert to YUV separately for writeback.
 */
static const u32 writeback_formats[] = {
	DRM_FORMAT_RGB332,
	DRM_FORMAT_ARGB4444,
	DRM_FORMAT_XRGB4444,
	DRM_FORMAT_ARGB1555,
	DRM_FORMAT_XRGB1555,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_BGR888,
	DRM_FORMAT_RGB888,
	DRM_FORMAT_BGRA8888,
	DRM_FORMAT_BGRX8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_XRGB8888,
};

int rcar_du_writeback_init(struct rcar_du_device *rcdu,
			   struct rcar_du_crtc *rcrtc)
{
	struct drm_writeback_connector *wb_conn = &rcrtc->writeback;

	drm_connector_helper_add(&wb_conn->base,
				 &rcar_du_wb_conn_helper_funcs);

	return drm_writeback_connector_init(&rcdu->ddev, wb_conn,
					    &rcar_du_wb_conn_funcs,
					    &rcar_du_wb_enc_helper_funcs,
					    writeback_formats,
					    ARRAY_SIZE(writeback_formats),
					    1 << drm_crtc_index(&rcrtc->crtc));
}

void rcar_du_writeback_setup(struct rcar_du_crtc *rcrtc,
			     struct vsp1_du_writeback_config *cfg)
{
	struct rcar_du_wb_conn_state *wb_state;
	struct drm_connector_state *state;
	struct rcar_du_wb_job *rjob;
	struct drm_framebuffer *fb;
	unsigned int i;

	state = rcrtc->writeback.base.state;
	if (!state || !state->writeback_job)
		return;

	fb = state->writeback_job->fb;
	rjob = state->writeback_job->priv;
	wb_state = to_rcar_wb_conn_state(state);

	cfg->pixelformat = wb_state->format->v4l2;
	cfg->pitch = fb->pitches[0];

	for (i = 0; i < wb_state->format->planes; ++i)
		cfg->mem[i] = sg_dma_address(rjob->sg_tables[i].sgl)
			    + fb->offsets[i];

	drm_writeback_queue_job(&rcrtc->writeback, state);
}

void rcar_du_writeback_complete(struct rcar_du_crtc *rcrtc)
{
	drm_writeback_signal_completion(&rcrtc->writeback, 0);
}
