/*
 * rcar_du_encoder.c  --  R-Car Display Unit Encoder
 *
 * 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/export.h>

#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_panel.h>

#include "rcar_du_drv.h"
#include "rcar_du_encoder.h"
#include "rcar_du_kms.h"
#include "rcar_du_lvdscon.h"
#include "rcar_du_lvdsenc.h"

/* -----------------------------------------------------------------------------
 * Encoder
 */

static void rcar_du_encoder_disable(struct drm_encoder *encoder)
{
	struct rcar_du_encoder *renc = to_rcar_encoder(encoder);

	if (renc->connector && renc->connector->panel) {
		drm_panel_disable(renc->connector->panel);
		drm_panel_unprepare(renc->connector->panel);
	}

	if (renc->lvds)
		rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false);
}

static void rcar_du_encoder_enable(struct drm_encoder *encoder)
{
	struct rcar_du_encoder *renc = to_rcar_encoder(encoder);

	if (renc->lvds)
		rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true);

	if (renc->connector && renc->connector->panel) {
		drm_panel_prepare(renc->connector->panel);
		drm_panel_enable(renc->connector->panel);
	}
}

static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
					struct drm_crtc_state *crtc_state,
					struct drm_connector_state *conn_state)
{
	struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
	const struct drm_display_mode *mode = &crtc_state->mode;
	struct drm_connector *connector = conn_state->connector;
	struct drm_device *dev = encoder->dev;

	/*
	 * Only panel-related encoder types require validation here, everything
	 * else is handled by the bridge drivers.
	 */
	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
		const struct drm_display_mode *panel_mode;

		if (list_empty(&connector->modes)) {
			dev_dbg(dev->dev, "encoder: empty modes list\n");
			return -EINVAL;
		}

		panel_mode = list_first_entry(&connector->modes,
					      struct drm_display_mode, head);

		/* We're not allowed to modify the resolution. */
		if (mode->hdisplay != panel_mode->hdisplay ||
		    mode->vdisplay != panel_mode->vdisplay)
			return -EINVAL;

		/*
		 * The flat panel mode is fixed, just copy it to the adjusted
		 * mode.
		 */
		drm_mode_copy(adjusted_mode, panel_mode);
	}

	if (renc->lvds)
		rcar_du_lvdsenc_atomic_check(renc->lvds, adjusted_mode);

	return 0;
}

static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
				     struct drm_crtc_state *crtc_state,
				     struct drm_connector_state *conn_state)
{
	struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
	struct drm_display_info *info = &conn_state->connector->display_info;
	enum rcar_lvds_mode mode;

	rcar_du_crtc_route_output(crtc_state->crtc, renc->output);

	if (!renc->lvds) {
		/*
		 * The DU driver creates connectors only for the outputs of the
		 * internal LVDS encoders.
		 */
		renc->connector = NULL;
		return;
	}

	renc->connector = to_rcar_connector(conn_state->connector);

	if (!info->num_bus_formats || !info->bus_formats) {
		dev_err(encoder->dev->dev, "no LVDS bus format reported\n");
		return;
	}

	switch (info->bus_formats[0]) {
	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
		mode = RCAR_LVDS_MODE_JEIDA;
		break;
	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
		mode = RCAR_LVDS_MODE_VESA;
		break;
	default:
		dev_err(encoder->dev->dev,
			"unsupported LVDS bus format 0x%04x\n",
			info->bus_formats[0]);
		return;
	}

	if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
		mode |= RCAR_LVDS_MODE_MIRROR;

	rcar_du_lvdsenc_set_mode(renc->lvds, mode);
}

static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
	.atomic_mode_set = rcar_du_encoder_mode_set,
	.disable = rcar_du_encoder_disable,
	.enable = rcar_du_encoder_enable,
	.atomic_check = rcar_du_encoder_atomic_check,
};

static const struct drm_encoder_funcs encoder_funcs = {
	.destroy = drm_encoder_cleanup,
};

int rcar_du_encoder_init(struct rcar_du_device *rcdu,
			 enum rcar_du_output output,
			 struct device_node *enc_node,
			 struct device_node *con_node)
{
	struct rcar_du_encoder *renc;
	struct drm_encoder *encoder;
	struct drm_bridge *bridge = NULL;
	int ret;

	renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL);
	if (renc == NULL)
		return -ENOMEM;

	renc->output = output;
	encoder = rcar_encoder_to_drm_encoder(renc);

	switch (output) {
	case RCAR_DU_OUTPUT_LVDS0:
		renc->lvds = rcdu->lvds[0];
		break;

	case RCAR_DU_OUTPUT_LVDS1:
		renc->lvds = rcdu->lvds[1];
		break;

	default:
		break;
	}

	if (enc_node) {
		dev_dbg(rcdu->dev, "initializing encoder %s for output %u\n",
			of_node_full_name(enc_node), output);

		/* Locate the DRM bridge from the encoder DT node. */
		bridge = of_drm_find_bridge(enc_node);
		if (!bridge) {
			ret = -EPROBE_DEFER;
			goto done;
		}
	} else {
		dev_dbg(rcdu->dev,
			"initializing internal encoder for output %u\n",
			output);
	}

	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
			       DRM_MODE_ENCODER_NONE, NULL);
	if (ret < 0)
		goto done;

	drm_encoder_helper_add(encoder, &encoder_helper_funcs);

	if (bridge) {
		/*
		 * Attach the bridge to the encoder. The bridge will create the
		 * connector.
		 */
		ret = drm_bridge_attach(encoder, bridge, NULL);
		if (ret) {
			drm_encoder_cleanup(encoder);
			return ret;
		}
	} else {
		/* There's no bridge, create the connector manually. */
		switch (output) {
		case RCAR_DU_OUTPUT_LVDS0:
		case RCAR_DU_OUTPUT_LVDS1:
			ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
			break;

		default:
			ret = -EINVAL;
			break;
		}
	}

done:
	if (ret < 0) {
		if (encoder->name)
			encoder->funcs->destroy(encoder);
		devm_kfree(rcdu->dev, renc);
	}

	return ret;
}
