/*
 * Copyright (C) STMicroelectronics SA 2014
 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
 *          Fabien Dessenne <fabien.dessenne@st.com>
 *          for STMicroelectronics.
 * License terms:  GNU General Public License (GPL), version 2
 */

#include <linux/component.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reset.h>

#include <drm/drmP.h>

#include "sti_compositor.h"
#include "sti_drm_crtc.h"
#include "sti_drm_drv.h"
#include "sti_drm_plane.h"
#include "sti_gdp.h"
#include "sti_vtg.h"

/*
 * stiH407 compositor properties
 */
struct sti_compositor_data stih407_compositor_data = {
	.nb_subdev = 8,
	.subdev_desc = {
			{STI_CURSOR_SUBDEV, (int)STI_CURSOR, 0x000},
			{STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
			{STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
			{STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300},
			{STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400},
			{STI_VID_SUBDEV, (int)STI_VID_0, 0x700},
			{STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00},
			{STI_MIXER_AUX_SUBDEV, STI_MIXER_AUX, 0xD00},
	},
};

/*
 * stiH416 compositor properties
 * Note:
 * on stih416 MIXER_AUX has a different base address from MIXER_MAIN
 * Moreover, GDPx is different for Main and Aux Mixer. So this subdev map does
 * not fit for stiH416 if we want to enable the MIXER_AUX.
 */
struct sti_compositor_data stih416_compositor_data = {
	.nb_subdev = 3,
	.subdev_desc = {
			{STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
			{STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
			{STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00}
	},
};

static int sti_compositor_init_subdev(struct sti_compositor *compo,
		struct sti_compositor_subdev_descriptor *desc,
		unsigned int array_size)
{
	unsigned int i, mixer_id = 0, layer_id = 0;

	for (i = 0; i < array_size; i++) {
		switch (desc[i].type) {
		case STI_MIXER_MAIN_SUBDEV:
		case STI_MIXER_AUX_SUBDEV:
			compo->mixer[mixer_id++] =
			    sti_mixer_create(compo->dev, desc[i].id,
					     compo->regs + desc[i].offset);
			break;
		case STI_GPD_SUBDEV:
		case STI_VID_SUBDEV:
		case STI_CURSOR_SUBDEV:
			compo->layer[layer_id++] =
			    sti_layer_create(compo->dev, desc[i].id,
					     compo->regs + desc[i].offset);
			break;
		default:
			DRM_ERROR("Unknow subdev compoment type\n");
			return 1;
		}

	}
	compo->nb_mixers = mixer_id;
	compo->nb_layers = layer_id;

	return 0;
}

static int sti_compositor_bind(struct device *dev, struct device *master,
	void *data)
{
	struct sti_compositor *compo = dev_get_drvdata(dev);
	struct drm_device *drm_dev = data;
	unsigned int i, crtc = 0, plane = 0;
	struct sti_drm_private *dev_priv = drm_dev->dev_private;
	struct drm_plane *cursor = NULL;
	struct drm_plane *primary = NULL;

	dev_priv->compo = compo;

	for (i = 0; i < compo->nb_layers; i++) {
		if (compo->layer[i]) {
			enum sti_layer_desc desc = compo->layer[i]->desc;
			enum sti_layer_type type = desc & STI_LAYER_TYPE_MASK;
			enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;

			if (crtc < compo->nb_mixers)
				plane_type = DRM_PLANE_TYPE_PRIMARY;

			switch (type) {
			case STI_CUR:
				cursor = sti_drm_plane_init(drm_dev,
						compo->layer[i],
						1, DRM_PLANE_TYPE_CURSOR);
				break;
			case STI_GDP:
			case STI_VID:
				primary = sti_drm_plane_init(drm_dev,
						compo->layer[i],
						(1 << compo->nb_mixers) - 1,
						plane_type);
				plane++;
				break;
			case STI_BCK:
			case STI_VDP:
				break;
			}

			/* The first planes are reserved for primary planes*/
			if (crtc < compo->nb_mixers && primary) {
				sti_drm_crtc_init(drm_dev, compo->mixer[crtc],
						primary, cursor);
				crtc++;
				cursor = NULL;
				primary = NULL;
			}
		}
	}

	drm_vblank_init(drm_dev, crtc);
	/* Allow usage of vblank without having to call drm_irq_install */
	drm_dev->irq_enabled = 1;

	DRM_DEBUG_DRIVER("Initialized %d DRM CRTC(s) and %d DRM plane(s)\n",
			 crtc, plane);
	DRM_DEBUG_DRIVER("DRM plane(s) for VID/VDP not created yet\n");

	return 0;
}

static void sti_compositor_unbind(struct device *dev, struct device *master,
	void *data)
{
	/* do nothing */
}

static const struct component_ops sti_compositor_ops = {
	.bind	= sti_compositor_bind,
	.unbind	= sti_compositor_unbind,
};

static const struct of_device_id compositor_of_match[] = {
	{
		.compatible = "st,stih416-compositor",
		.data = &stih416_compositor_data,
	}, {
		.compatible = "st,stih407-compositor",
		.data = &stih407_compositor_data,
	}, {
		/* end node */
	}
};
MODULE_DEVICE_TABLE(of, compositor_of_match);

static int sti_compositor_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct device_node *vtg_np;
	struct sti_compositor *compo;
	struct resource *res;
	int err;

	compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL);
	if (!compo) {
		DRM_ERROR("Failed to allocate compositor context\n");
		return -ENOMEM;
	}
	compo->dev = dev;
	compo->vtg_vblank_nb.notifier_call = sti_drm_crtc_vblank_cb;

	/* populate data structure depending on compatibility */
	BUG_ON(!of_match_node(compositor_of_match, np)->data);

	memcpy(&compo->data, of_match_node(compositor_of_match, np)->data,
	       sizeof(struct sti_compositor_data));

	/* Get Memory ressources */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		DRM_ERROR("Get memory resource failed\n");
		return -ENXIO;
	}
	compo->regs = devm_ioremap(dev, res->start, resource_size(res));
	if (compo->regs == NULL) {
		DRM_ERROR("Register mapping failed\n");
		return -ENXIO;
	}

	/* Get clock resources */
	compo->clk_compo_main = devm_clk_get(dev, "compo_main");
	if (IS_ERR(compo->clk_compo_main)) {
		DRM_ERROR("Cannot get compo_main clock\n");
		return PTR_ERR(compo->clk_compo_main);
	}

	compo->clk_compo_aux = devm_clk_get(dev, "compo_aux");
	if (IS_ERR(compo->clk_compo_aux)) {
		DRM_ERROR("Cannot get compo_aux clock\n");
		return PTR_ERR(compo->clk_compo_aux);
	}

	compo->clk_pix_main = devm_clk_get(dev, "pix_main");
	if (IS_ERR(compo->clk_pix_main)) {
		DRM_ERROR("Cannot get pix_main clock\n");
		return PTR_ERR(compo->clk_pix_main);
	}

	compo->clk_pix_aux = devm_clk_get(dev, "pix_aux");
	if (IS_ERR(compo->clk_pix_aux)) {
		DRM_ERROR("Cannot get pix_aux clock\n");
		return PTR_ERR(compo->clk_pix_aux);
	}

	/* Get reset resources */
	compo->rst_main = devm_reset_control_get(dev, "compo-main");
	/* Take compo main out of reset */
	if (!IS_ERR(compo->rst_main))
		reset_control_deassert(compo->rst_main);

	compo->rst_aux = devm_reset_control_get(dev, "compo-aux");
	/* Take compo aux out of reset */
	if (!IS_ERR(compo->rst_aux))
		reset_control_deassert(compo->rst_aux);

	vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0);
	if (vtg_np)
		compo->vtg_main = of_vtg_find(vtg_np);

	vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 1);
	if (vtg_np)
		compo->vtg_aux = of_vtg_find(vtg_np);

	/* Initialize compositor subdevices */
	err = sti_compositor_init_subdev(compo, compo->data.subdev_desc,
					 compo->data.nb_subdev);
	if (err)
		return err;

	platform_set_drvdata(pdev, compo);

	return component_add(&pdev->dev, &sti_compositor_ops);
}

static int sti_compositor_remove(struct platform_device *pdev)
{
	component_del(&pdev->dev, &sti_compositor_ops);
	return 0;
}

static struct platform_driver sti_compositor_driver = {
	.driver = {
		.name = "sti-compositor",
		.of_match_table = compositor_of_match,
	},
	.probe = sti_compositor_probe,
	.remove = sti_compositor_remove,
};

module_platform_driver(sti_compositor_driver);

MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");
