/*
 * 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/clk.h>

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

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

static void sti_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
{
	DRM_DEBUG_KMS("\n");
}

static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
{
	struct sti_mixer *mixer = to_sti_mixer(crtc);
	struct device *dev = mixer->dev;
	struct sti_compositor *compo = dev_get_drvdata(dev);

	compo->enable = true;

	/* Prepare and enable the compo IP clock */
	if (mixer->id == STI_MIXER_MAIN) {
		if (clk_prepare_enable(compo->clk_compo_main))
			DRM_INFO("Failed to prepare/enable compo_main clk\n");
	} else {
		if (clk_prepare_enable(compo->clk_compo_aux))
			DRM_INFO("Failed to prepare/enable compo_aux clk\n");
	}
}

static void sti_drm_crtc_commit(struct drm_crtc *crtc)
{
	struct sti_mixer *mixer = to_sti_mixer(crtc);
	struct device *dev = mixer->dev;
	struct sti_compositor *compo = dev_get_drvdata(dev);
	struct sti_layer *layer;

	if ((!mixer || !compo)) {
		DRM_ERROR("Can not find mixer or compositor)\n");
		return;
	}

	/* get GDP which is reserved to the CRTC FB */
	layer = to_sti_layer(crtc->primary);
	if (layer)
		sti_layer_commit(layer);
	else
		DRM_ERROR("Can not find CRTC dedicated plane (GDP0)\n");

	/* Enable layer on mixer */
	if (sti_mixer_set_layer_status(mixer, layer, true))
		DRM_ERROR("Can not enable layer at mixer\n");
}

static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc,
				    const struct drm_display_mode *mode,
				    struct drm_display_mode *adjusted_mode)
{
	/* accept the provided drm_display_mode, do not fix it up */
	return true;
}

static int
sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
		      struct drm_display_mode *adjusted_mode, int x, int y,
		      struct drm_framebuffer *old_fb)
{
	struct sti_mixer *mixer = to_sti_mixer(crtc);
	struct device *dev = mixer->dev;
	struct sti_compositor *compo = dev_get_drvdata(dev);
	struct sti_layer *layer;
	struct clk *clk;
	int rate = mode->clock * 1000;
	int res;
	unsigned int w, h;

	DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d mode:%d (%s)\n",
		      crtc->base.id, sti_mixer_to_str(mixer),
		      crtc->primary->fb->base.id, mode->base.id, mode->name);

	DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
		      mode->vrefresh, mode->clock,
		      mode->hdisplay,
		      mode->hsync_start, mode->hsync_end,
		      mode->htotal,
		      mode->vdisplay,
		      mode->vsync_start, mode->vsync_end,
		      mode->vtotal, mode->type, mode->flags);

	/* Set rate and prepare/enable pixel clock */
	if (mixer->id == STI_MIXER_MAIN)
		clk = compo->clk_pix_main;
	else
		clk = compo->clk_pix_aux;

	res = clk_set_rate(clk, rate);
	if (res < 0) {
		DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
		return -EINVAL;
	}
	if (clk_prepare_enable(clk)) {
		DRM_ERROR("Failed to prepare/enable pix clk\n");
		return -EINVAL;
	}

	sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ?
			compo->vtg_main : compo->vtg_aux, &crtc->mode);

	/* a GDP is reserved to the CRTC FB */
	layer = to_sti_layer(crtc->primary);
	if (!layer) {
		DRM_ERROR("Can not find GDP0)\n");
		return -EINVAL;
	}

	/* copy the mode data adjusted by mode_fixup() into crtc->mode
	 * so that hardware can be set to proper mode
	 */
	memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));

	res = sti_mixer_set_layer_depth(mixer, layer);
	if (res) {
		DRM_ERROR("Can not set layer depth\n");
		return -EINVAL;
	}
	res = sti_mixer_active_video_area(mixer, &crtc->mode);
	if (res) {
		DRM_ERROR("Can not set active video area\n");
		return -EINVAL;
	}

	w = crtc->primary->fb->width - x;
	h = crtc->primary->fb->height - y;

	return sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode,
			mixer->id, 0, 0, w, h, x, y, w, h);
}

static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
				      struct drm_framebuffer *old_fb)
{
	struct sti_mixer *mixer = to_sti_mixer(crtc);
	struct sti_layer *layer;
	unsigned int w, h;
	int ret;

	DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d (%d,%d)\n",
		      crtc->base.id, sti_mixer_to_str(mixer),
		      crtc->primary->fb->base.id, x, y);

	/* GDP is reserved to the CRTC FB */
	layer = to_sti_layer(crtc->primary);
	if (!layer) {
		DRM_ERROR("Can not find GDP0)\n");
		ret = -EINVAL;
		goto out;
	}

	w = crtc->primary->fb->width - crtc->x;
	h = crtc->primary->fb->height - crtc->y;

	ret = sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode,
				mixer->id, 0, 0, w, h,
				crtc->x, crtc->y, w, h);
	if (ret) {
		DRM_ERROR("Can not prepare layer\n");
		goto out;
	}

	sti_drm_crtc_commit(crtc);
out:
	return ret;
}

static void sti_drm_crtc_load_lut(struct drm_crtc *crtc)
{
	/* do nothing */
}

static void sti_drm_crtc_disable(struct drm_crtc *crtc)
{
	struct sti_mixer *mixer = to_sti_mixer(crtc);
	struct device *dev = mixer->dev;
	struct sti_compositor *compo = dev_get_drvdata(dev);
	struct sti_layer *layer;

	if (!compo->enable)
		return;

	DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));

	/* Disable Background */
	sti_mixer_set_background_status(mixer, false);

	/* Disable GDP */
	layer = to_sti_layer(crtc->primary);
	if (!layer) {
		DRM_ERROR("Cannot find GDP0\n");
		return;
	}

	/* Disable layer at mixer level */
	if (sti_mixer_set_layer_status(mixer, layer, false))
		DRM_ERROR("Can not disable %s layer at mixer\n",
				sti_layer_to_str(layer));

	/* Wait a while to be sure that a Vsync event is received */
	msleep(WAIT_NEXT_VSYNC_MS);

	/* Then disable layer itself */
	sti_layer_disable(layer);

	drm_vblank_off(crtc->dev, mixer->id);

	/* Disable pixel clock and compo IP clocks */
	if (mixer->id == STI_MIXER_MAIN) {
		clk_disable_unprepare(compo->clk_pix_main);
		clk_disable_unprepare(compo->clk_compo_main);
	} else {
		clk_disable_unprepare(compo->clk_pix_aux);
		clk_disable_unprepare(compo->clk_compo_aux);
	}

	compo->enable = false;
}

static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
	.dpms = sti_drm_crtc_dpms,
	.prepare = sti_drm_crtc_prepare,
	.commit = sti_drm_crtc_commit,
	.mode_fixup = sti_drm_crtc_mode_fixup,
	.mode_set = sti_drm_crtc_mode_set,
	.mode_set_base = sti_drm_crtc_mode_set_base,
	.load_lut = sti_drm_crtc_load_lut,
	.disable = sti_drm_crtc_disable,
};

static int sti_drm_crtc_page_flip(struct drm_crtc *crtc,
				  struct drm_framebuffer *fb,
				  struct drm_pending_vblank_event *event,
				  uint32_t page_flip_flags)
{
	struct drm_device *drm_dev = crtc->dev;
	struct drm_framebuffer *old_fb;
	struct sti_mixer *mixer = to_sti_mixer(crtc);
	unsigned long flags;
	int ret;

	DRM_DEBUG_KMS("fb %d --> fb %d\n",
			crtc->primary->fb->base.id, fb->base.id);

	mutex_lock(&drm_dev->struct_mutex);

	old_fb = crtc->primary->fb;
	crtc->primary->fb = fb;
	ret = sti_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
	if (ret) {
		DRM_ERROR("failed\n");
		crtc->primary->fb = old_fb;
		goto out;
	}

	if (event) {
		event->pipe = mixer->id;

		ret = drm_vblank_get(drm_dev, event->pipe);
		if (ret) {
			DRM_ERROR("Cannot get vblank\n");
			goto out;
		}

		spin_lock_irqsave(&drm_dev->event_lock, flags);
		if (mixer->pending_event) {
			drm_vblank_put(drm_dev, event->pipe);
			ret = -EBUSY;
		} else {
			mixer->pending_event = event;
		}
		spin_unlock_irqrestore(&drm_dev->event_lock, flags);
	}
out:
	mutex_unlock(&drm_dev->struct_mutex);
	return ret;
}

static void sti_drm_crtc_destroy(struct drm_crtc *crtc)
{
	DRM_DEBUG_KMS("\n");
	drm_crtc_cleanup(crtc);
}

static int sti_drm_crtc_set_property(struct drm_crtc *crtc,
				     struct drm_property *property,
				     uint64_t val)
{
	DRM_DEBUG_KMS("\n");
	return 0;
}

int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
			   unsigned long event, void *data)
{
	struct drm_device *drm_dev;
	struct sti_compositor *compo =
		container_of(nb, struct sti_compositor, vtg_vblank_nb);
	int *crtc = data;
	unsigned long flags;
	struct sti_drm_private *priv;

	drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
	priv = drm_dev->dev_private;

	if ((event != VTG_TOP_FIELD_EVENT) &&
	    (event != VTG_BOTTOM_FIELD_EVENT)) {
		DRM_ERROR("unknown event: %lu\n", event);
		return -EINVAL;
	}

	drm_handle_vblank(drm_dev, *crtc);

	spin_lock_irqsave(&drm_dev->event_lock, flags);
	if (compo->mixer[*crtc]->pending_event) {
		drm_send_vblank_event(drm_dev, -1,
				compo->mixer[*crtc]->pending_event);
		drm_vblank_put(drm_dev, *crtc);
		compo->mixer[*crtc]->pending_event = NULL;
	}
	spin_unlock_irqrestore(&drm_dev->event_lock, flags);

	return 0;
}

int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
{
	struct sti_drm_private *dev_priv = dev->dev_private;
	struct sti_compositor *compo = dev_priv->compo;
	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;

	if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
			compo->vtg_main : compo->vtg_aux,
			vtg_vblank_nb, crtc)) {
		DRM_ERROR("Cannot register VTG notifier\n");
		return -EINVAL;
	}

	return 0;
}
EXPORT_SYMBOL(sti_drm_crtc_enable_vblank);

void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
{
	struct sti_drm_private *priv = dev->dev_private;
	struct sti_compositor *compo = priv->compo;
	struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
	unsigned long flags;

	DRM_DEBUG_DRIVER("\n");

	if (sti_vtg_unregister_client(crtc == STI_MIXER_MAIN ?
			compo->vtg_main : compo->vtg_aux, vtg_vblank_nb))
		DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");

	/* free the resources of the pending requests */
	spin_lock_irqsave(&dev->event_lock, flags);
	if (compo->mixer[crtc]->pending_event) {
		drm_vblank_put(dev, crtc);
		compo->mixer[crtc]->pending_event = NULL;
	}
	spin_unlock_irqrestore(&dev->event_lock, flags);

}
EXPORT_SYMBOL(sti_drm_crtc_disable_vblank);

static struct drm_crtc_funcs sti_crtc_funcs = {
	.set_config = drm_crtc_helper_set_config,
	.page_flip = sti_drm_crtc_page_flip,
	.destroy = sti_drm_crtc_destroy,
	.set_property = sti_drm_crtc_set_property,
};

bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
{
	struct sti_mixer *mixer = to_sti_mixer(crtc);

	if (mixer->id == STI_MIXER_MAIN)
		return true;

	return false;
}

int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
		struct drm_plane *primary, struct drm_plane *cursor)
{
	struct drm_crtc *crtc = &mixer->drm_crtc;
	int res;

	res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
			&sti_crtc_funcs);
	if (res) {
		DRM_ERROR("Can not initialze CRTC\n");
		return -EINVAL;
	}

	drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);

	DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
			 crtc->base.id, sti_mixer_to_str(mixer));

	return 0;
}
