/*
 * Copyright 2018 NXP
 *
 * 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.
 *
 * 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.
 */

#include <linux/module.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_plane.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_rect.h>
#include <video/imx-lcdif.h>

#include "lcdif-plane.h"

static uint32_t lcdif_pixel_formats[] = {
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_RGBX8888,
	DRM_FORMAT_RGBA8888,
	DRM_FORMAT_ARGB1555,
	DRM_FORMAT_XRGB1555,
	DRM_FORMAT_ABGR1555,
	DRM_FORMAT_XBGR1555,
	DRM_FORMAT_BGR565,
};

static int lcdif_plane_atomic_check(struct drm_plane *plane,
				    struct drm_plane_state *plane_state)
{
	int ret;
	struct drm_plane_state *old_state = plane->state;
	struct drm_framebuffer *fb = plane_state->fb;
	struct drm_framebuffer *old_fb = old_state->fb;
	struct drm_crtc_state *crtc_state;
	struct drm_display_mode *mode;
	struct drm_rect clip = { 0 };

	/* 'fb' should also be NULL which has been checked in
	 * the core sanity check function 'drm_atomic_plane_check()'
	 */
	if (!plane_state->crtc) {
		WARN_ON(fb);
		return 0;
	}

	/* lcdif crtc can only display from (0,0) for each plane */
	if (plane_state->crtc_x || plane_state->crtc_y)
		return -EINVAL;

	crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
							plane_state->crtc);
	mode = &crtc_state->adjusted_mode;

	clip.x2 = mode->hdisplay;
	clip.y2 = mode->vdisplay;

	ret = drm_plane_helper_check_state(plane_state, &clip,
					   DRM_PLANE_HELPER_NO_SCALING,
					   DRM_PLANE_HELPER_NO_SCALING,
					   false, true);
	if (ret)
		return ret;

	if (!plane_state->visible)
		return -EINVAL;

	/* force 'mode_changed' when fb pitches changed, since
	 * the pitch related registers configuration of LCDIF
	 * can not be done when LCDIF is running.
	 */
	if (old_fb && likely(!crtc_state->mode_changed)) {
		if (old_fb->pitches[0] != fb->pitches[0])
			crtc_state->mode_changed = true;
	}

	return 0;
}

static void lcdif_plane_atomic_update(struct drm_plane *plane,
				      struct drm_plane_state *old_state)
{
	struct lcdif_plane *lcdif_plane = to_lcdif_plane(plane);
	struct lcdif_soc *lcdif = lcdif_plane->lcdif;
	struct drm_plane_state *state = plane->state;
	struct drm_framebuffer *fb = state->fb;
	struct drm_gem_cma_object *gem_obj = NULL;
	u32 fb_addr, src_off, src_w, fb_idx, cpp, stride;
	bool crop;

	/* plane and crtc is disabling */
	if (!fb)
		return;

	/* TODO: for now we just update the next buf addr
	 * and the fb pixel format, since the mode set will
	 * be done in crtc's ->enable() helper func
	 */
	if (plane->type == DRM_PLANE_TYPE_PRIMARY)
		lcdif_set_pix_fmt(lcdif, fb->format->format);

	switch (plane->type) {
	case DRM_PLANE_TYPE_PRIMARY:
		/* TODO: only support RGB */
		gem_obj = drm_fb_cma_get_gem_obj(fb, 0);
		src_off = (state->src_y >> 16) * fb->pitches[0] +
			  (state->src_x >> 16) * fb->format->cpp[0];
		fb_addr = gem_obj->paddr + fb->offsets[0] + src_off;
		fb_idx  = 0;
		break;
	default:
		/* TODO: add overlay later */
		return;
	}

	lcdif_set_fb_addr(lcdif, fb_idx, fb_addr);

	/* config horizontal cropping if crtc needs modeset */
	if (unlikely(drm_atomic_crtc_needs_modeset(state->crtc->state))) {
		cpp = fb->format->cpp[0];
		stride = DIV_ROUND_UP(fb->pitches[0], cpp);

		src_w = state->src_w >> 16;
		WARN_ON(src_w > fb->width);

		crop  = src_w != stride ? true : false;
		lcdif_set_fb_hcrop(lcdif, src_w, stride, crop);
	}

	lcdif_enable_controller(lcdif);
}

static void lcdif_plane_atomic_disable(struct drm_plane *plane,
				       struct drm_plane_state *old_state)
{
	struct drm_plane_state *state = plane->state;
	struct drm_framebuffer *fb = state->fb;

	WARN_ON(fb);

	/* TODO: CRTC disabled has been done by CRTC helper function,
	 * so it seems that no more required, the only possible thing
	 * is to set next buf addr to 0 in CRTC
	 */
}

static const struct drm_plane_helper_funcs lcdif_plane_helper_funcs = {
	.atomic_check	= lcdif_plane_atomic_check,
	.atomic_update	= lcdif_plane_atomic_update,
	.atomic_disable	= lcdif_plane_atomic_disable,
};

static void lcdif_plane_destroy(struct drm_plane *plane)
{
	struct lcdif_plane *lcdif_plane = to_lcdif_plane(plane);

	drm_plane_cleanup(plane);
	kfree(lcdif_plane);
}

static const struct drm_plane_funcs lcdif_plane_funcs = {
	.update_plane	= drm_atomic_helper_update_plane,
	.disable_plane	= drm_atomic_helper_disable_plane,
	.destroy	= lcdif_plane_destroy,
	.reset		= drm_atomic_helper_plane_reset,
	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
};

struct lcdif_plane *lcdif_plane_init(struct drm_device *dev,
				     struct lcdif_soc *lcdif,
				     unsigned int possible_crtcs,
				     enum drm_plane_type type,
				     unsigned int zpos)
{
	int ret;
	struct lcdif_plane *lcdif_plane;

	/* lcdif doesn't support fb modifiers */
	if (zpos || dev->mode_config.allow_fb_modifiers)
		return ERR_PTR(-EINVAL);

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

	lcdif_plane->lcdif = lcdif;

	drm_plane_helper_add(&lcdif_plane->base, &lcdif_plane_helper_funcs);
	ret = drm_universal_plane_init(dev, &lcdif_plane->base, possible_crtcs,
				       &lcdif_plane_funcs, lcdif_pixel_formats,
				       ARRAY_SIZE(lcdif_pixel_formats), NULL,
				       type, NULL);
	if (ret) {
		kfree(lcdif_plane);
		return ERR_PTR(ret);
	}

	ret = drm_plane_create_zpos_immutable_property(&lcdif_plane->base, zpos);
	if (ret) {
		kfree(lcdif_plane);
		return ERR_PTR(ret);
	}

	return lcdif_plane;
}

void lcdif_plane_deinit(struct drm_device *dev,
			struct lcdif_plane *lcdif_plane)
{
	struct drm_plane *plane = &lcdif_plane->base;

	if (plane->zpos_property)
		drm_property_destroy(dev, plane->zpos_property);

	lcdif_plane_destroy(plane);
}
