/*
 * Copyright (C) 2014 Traphandler
 * Copyright (C) 2014 Free Electrons
 * Copyright (C) 2014 Atmel
 *
 * Author: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <linux/of_graph.h>

#include <drm/drmP.h>
#include <drm/drm_of.h>

#include "atmel_hlcdc_dc.h"

/**
 * Atmel HLCDC RGB connector structure
 *
 * This structure stores RGB slave device information.
 *
 * @connector: DRM connector
 * @encoder: DRM encoder
 * @dc: pointer to the atmel_hlcdc_dc structure
 * @panel: panel connected on the RGB output
 */
struct atmel_hlcdc_rgb_output {
	struct drm_connector connector;
	struct drm_encoder encoder;
	struct atmel_hlcdc_dc *dc;
	struct drm_panel *panel;
};

static inline struct atmel_hlcdc_rgb_output *
drm_connector_to_atmel_hlcdc_rgb_output(struct drm_connector *connector)
{
	return container_of(connector, struct atmel_hlcdc_rgb_output,
			    connector);
}

static inline struct atmel_hlcdc_rgb_output *
drm_encoder_to_atmel_hlcdc_rgb_output(struct drm_encoder *encoder)
{
	return container_of(encoder, struct atmel_hlcdc_rgb_output, encoder);
}

static void atmel_hlcdc_rgb_encoder_enable(struct drm_encoder *encoder)
{
	struct atmel_hlcdc_rgb_output *rgb =
			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);

	if (rgb->panel) {
		drm_panel_prepare(rgb->panel);
		drm_panel_enable(rgb->panel);
	}
}

static void atmel_hlcdc_rgb_encoder_disable(struct drm_encoder *encoder)
{
	struct atmel_hlcdc_rgb_output *rgb =
			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);

	if (rgb->panel) {
		drm_panel_disable(rgb->panel);
		drm_panel_unprepare(rgb->panel);
	}
}

static const struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = {
	.disable = atmel_hlcdc_rgb_encoder_disable,
	.enable = atmel_hlcdc_rgb_encoder_enable,
};

static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder)
{
	drm_encoder_cleanup(encoder);
	memset(encoder, 0, sizeof(*encoder));
}

static const struct drm_encoder_funcs atmel_hlcdc_panel_encoder_funcs = {
	.destroy = atmel_hlcdc_rgb_encoder_destroy,
};

static int atmel_hlcdc_panel_get_modes(struct drm_connector *connector)
{
	struct atmel_hlcdc_rgb_output *rgb =
			drm_connector_to_atmel_hlcdc_rgb_output(connector);

	if (rgb->panel)
		return rgb->panel->funcs->get_modes(rgb->panel);

	return 0;
}

static int atmel_hlcdc_rgb_mode_valid(struct drm_connector *connector,
				      struct drm_display_mode *mode)
{
	struct atmel_hlcdc_rgb_output *rgb =
			drm_connector_to_atmel_hlcdc_rgb_output(connector);

	return atmel_hlcdc_dc_mode_valid(rgb->dc, mode);
}

static const struct drm_connector_helper_funcs atmel_hlcdc_panel_connector_helper_funcs = {
	.get_modes = atmel_hlcdc_panel_get_modes,
	.mode_valid = atmel_hlcdc_rgb_mode_valid,
};

static enum drm_connector_status
atmel_hlcdc_panel_connector_detect(struct drm_connector *connector, bool force)
{
	struct atmel_hlcdc_rgb_output *rgb =
			drm_connector_to_atmel_hlcdc_rgb_output(connector);

	if (rgb->panel)
		return connector_status_connected;

	return connector_status_disconnected;
}

static void
atmel_hlcdc_panel_connector_destroy(struct drm_connector *connector)
{
	struct atmel_hlcdc_rgb_output *rgb =
			drm_connector_to_atmel_hlcdc_rgb_output(connector);

	if (rgb->panel)
		drm_panel_detach(rgb->panel);

	drm_connector_cleanup(connector);
}

static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
	.dpms = drm_atomic_helper_connector_dpms,
	.detect = atmel_hlcdc_panel_connector_detect,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.destroy = atmel_hlcdc_panel_connector_destroy,
	.reset = drm_atomic_helper_connector_reset,
	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};

static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
{
	struct atmel_hlcdc_dc *dc = dev->dev_private;
	struct atmel_hlcdc_rgb_output *output;
	struct drm_panel *panel;
	struct drm_bridge *bridge;
	int ret;

	ret = drm_of_find_panel_or_bridge(dev->dev->of_node, 0, endpoint,
					  &panel, &bridge);
	if (ret)
		return ret;

	output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL);
	if (!output)
		return -EINVAL;

	output->dc = dc;

	drm_encoder_helper_add(&output->encoder,
			       &atmel_hlcdc_panel_encoder_helper_funcs);
	ret = drm_encoder_init(dev, &output->encoder,
			       &atmel_hlcdc_panel_encoder_funcs,
			       DRM_MODE_ENCODER_NONE, NULL);
	if (ret)
		return ret;

	output->encoder.possible_crtcs = 0x1;

	if (panel) {
		output->connector.dpms = DRM_MODE_DPMS_OFF;
		output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
		drm_connector_helper_add(&output->connector,
				&atmel_hlcdc_panel_connector_helper_funcs);
		ret = drm_connector_init(dev, &output->connector,
					 &atmel_hlcdc_panel_connector_funcs,
					 DRM_MODE_CONNECTOR_Unknown);
		if (ret)
			goto err_encoder_cleanup;

		drm_mode_connector_attach_encoder(&output->connector,
						  &output->encoder);

		ret = drm_panel_attach(panel, &output->connector);
		if (ret) {
			drm_connector_cleanup(&output->connector);
			goto err_encoder_cleanup;
		}

		output->panel = panel;

		return 0;
	}

	if (bridge) {
		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
		if (!ret)
			return 0;
	}

err_encoder_cleanup:
	drm_encoder_cleanup(&output->encoder);

	return ret;
}

int atmel_hlcdc_create_outputs(struct drm_device *dev)
{
	int endpoint, ret = 0;

	for (endpoint = 0; !ret; endpoint++)
		ret = atmel_hlcdc_attach_endpoint(dev, endpoint);

	/* At least one device was successfully attached.*/
	if (ret == -ENODEV && endpoint)
		return 0;

	return ret;
}
