// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
 */

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include <drm/drm_vblank.h>

#include "tidss_crtc.h"
#include "tidss_dispc.h"
#include "tidss_drv.h"
#include "tidss_encoder.h"
#include "tidss_kms.h"
#include "tidss_plane.h"

static void tidss_atomic_commit_tail(struct drm_atomic_state *old_state)
{
	struct drm_device *ddev = old_state->dev;
	struct tidss_device *tidss = to_tidss(ddev);

	dev_dbg(ddev->dev, "%s\n", __func__);

	tidss_runtime_get(tidss);

	drm_atomic_helper_commit_modeset_disables(ddev, old_state);
	drm_atomic_helper_commit_planes(ddev, old_state, 0);
	drm_atomic_helper_commit_modeset_enables(ddev, old_state);

	drm_atomic_helper_commit_hw_done(old_state);
	drm_atomic_helper_wait_for_flip_done(ddev, old_state);

	drm_atomic_helper_cleanup_planes(ddev, old_state);

	tidss_runtime_put(tidss);
}

static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = {
	.atomic_commit_tail = tidss_atomic_commit_tail,
};

static int tidss_atomic_check(struct drm_device *ddev,
			      struct drm_atomic_state *state)
{
	struct drm_plane_state *opstate;
	struct drm_plane_state *npstate;
	struct drm_plane *plane;
	struct drm_crtc_state *cstate;
	struct drm_crtc *crtc;
	int ret, i;

	ret = drm_atomic_helper_check(ddev, state);
	if (ret)
		return ret;

	/*
	 * Add all active planes on a CRTC to the atomic state, if
	 * x/y/z position or activity of any plane on that CRTC
	 * changes. This is needed for updating the plane positions in
	 * tidss_crtc_position_planes() which is called from
	 * crtc_atomic_enable() and crtc_atomic_flush(). We have an
	 * extra flag to to mark x,y-position changes and together
	 * with zpos_changed the condition recognizes all the above
	 * cases.
	 */
	for_each_oldnew_plane_in_state(state, plane, opstate, npstate, i) {
		if (!npstate->crtc || !npstate->visible)
			continue;

		if (!opstate->crtc || opstate->crtc_x != npstate->crtc_x ||
		    opstate->crtc_y != npstate->crtc_y) {
			cstate = drm_atomic_get_crtc_state(state,
							   npstate->crtc);
			if (IS_ERR(cstate))
				return PTR_ERR(cstate);
			to_tidss_crtc_state(cstate)->plane_pos_changed = true;
		}
	}

	for_each_new_crtc_in_state(state, crtc, cstate, i) {
		if (to_tidss_crtc_state(cstate)->plane_pos_changed ||
		    cstate->zpos_changed) {
			ret = drm_atomic_add_affected_planes(state, crtc);
			if (ret)
				return ret;
		}
	}

	return 0;
}

static const struct drm_mode_config_funcs mode_config_funcs = {
	.fb_create = drm_gem_fb_create,
	.atomic_check = tidss_atomic_check,
	.atomic_commit = drm_atomic_helper_commit,
};

static int tidss_dispc_modeset_init(struct tidss_device *tidss)
{
	struct device *dev = tidss->dev;
	unsigned int fourccs_len;
	const u32 *fourccs = dispc_plane_formats(tidss->dispc, &fourccs_len);
	unsigned int i;

	struct pipe {
		u32 hw_videoport;
		struct drm_bridge *bridge;
		u32 enc_type;
	};

	const struct dispc_features *feat = tidss->feat;
	u32 max_vps = feat->num_vps;
	u32 max_planes = feat->num_planes;

	struct pipe pipes[TIDSS_MAX_PORTS];
	u32 num_pipes = 0;
	u32 crtc_mask;

	/* first find all the connected panels & bridges */

	for (i = 0; i < max_vps; i++) {
		struct drm_panel *panel;
		struct drm_bridge *bridge;
		u32 enc_type = DRM_MODE_ENCODER_NONE;
		int ret;

		ret = drm_of_find_panel_or_bridge(dev->of_node, i, 0,
						  &panel, &bridge);
		if (ret == -ENODEV) {
			dev_dbg(dev, "no panel/bridge for port %d\n", i);
			continue;
		} else if (ret) {
			dev_dbg(dev, "port %d probe returned %d\n", i, ret);
			return ret;
		}

		if (panel) {
			u32 conn_type;

			dev_dbg(dev, "Setting up panel for port %d\n", i);

			switch (feat->vp_bus_type[i]) {
			case DISPC_VP_OLDI:
				enc_type = DRM_MODE_ENCODER_LVDS;
				conn_type = DRM_MODE_CONNECTOR_LVDS;
				break;
			case DISPC_VP_DPI:
				enc_type = DRM_MODE_ENCODER_DPI;
				conn_type = DRM_MODE_CONNECTOR_LVDS;
				break;
			default:
				WARN_ON(1);
				return -EINVAL;
			}

			if (panel->connector_type != conn_type) {
				dev_err(dev,
					"%s: Panel %s has incompatible connector type for vp%d (%d != %d)\n",
					 __func__, dev_name(panel->dev), i,
					 panel->connector_type, conn_type);
				return -EINVAL;
			}

			bridge = devm_drm_panel_bridge_add(dev, panel);
			if (IS_ERR(bridge)) {
				dev_err(dev,
					"failed to set up panel bridge for port %d\n",
					i);
				return PTR_ERR(bridge);
			}
		}

		pipes[num_pipes].hw_videoport = i;
		pipes[num_pipes].bridge = bridge;
		pipes[num_pipes].enc_type = enc_type;
		num_pipes++;
	}

	/* all planes can be on any crtc */
	crtc_mask = (1 << num_pipes) - 1;

	/* then create a plane, a crtc and an encoder for each panel/bridge */

	for (i = 0; i < num_pipes; ++i) {
		struct tidss_plane *tplane;
		struct tidss_crtc *tcrtc;
		struct drm_encoder *enc;
		u32 hw_plane_id = feat->vid_order[tidss->num_planes];
		int ret;

		tplane = tidss_plane_create(tidss, hw_plane_id,
					    DRM_PLANE_TYPE_PRIMARY, crtc_mask,
					    fourccs, fourccs_len);
		if (IS_ERR(tplane)) {
			dev_err(tidss->dev, "plane create failed\n");
			return PTR_ERR(tplane);
		}

		tidss->planes[tidss->num_planes++] = &tplane->plane;

		tcrtc = tidss_crtc_create(tidss, pipes[i].hw_videoport,
					  &tplane->plane);
		if (IS_ERR(tcrtc)) {
			dev_err(tidss->dev, "crtc create failed\n");
			return PTR_ERR(tcrtc);
		}

		tidss->crtcs[tidss->num_crtcs++] = &tcrtc->crtc;

		enc = tidss_encoder_create(tidss, pipes[i].enc_type,
					   1 << tcrtc->crtc.index);
		if (IS_ERR(enc)) {
			dev_err(tidss->dev, "encoder create failed\n");
			return PTR_ERR(enc);
		}

		ret = drm_bridge_attach(enc, pipes[i].bridge, NULL, 0);
		if (ret) {
			dev_err(tidss->dev, "bridge attach failed: %d\n", ret);
			return ret;
		}
	}

	/* create overlay planes of the leftover planes */

	while (tidss->num_planes < max_planes) {
		struct tidss_plane *tplane;
		u32 hw_plane_id = feat->vid_order[tidss->num_planes];

		tplane = tidss_plane_create(tidss, hw_plane_id,
					    DRM_PLANE_TYPE_OVERLAY, crtc_mask,
					    fourccs, fourccs_len);

		if (IS_ERR(tplane)) {
			dev_err(tidss->dev, "plane create failed\n");
			return PTR_ERR(tplane);
		}

		tidss->planes[tidss->num_planes++] = &tplane->plane;
	}

	return 0;
}

int tidss_modeset_init(struct tidss_device *tidss)
{
	struct drm_device *ddev = &tidss->ddev;
	unsigned int i;
	int ret;

	dev_dbg(tidss->dev, "%s\n", __func__);

	ret = drmm_mode_config_init(ddev);
	if (ret)
		return ret;

	ddev->mode_config.min_width = 8;
	ddev->mode_config.min_height = 8;
	ddev->mode_config.max_width = 8096;
	ddev->mode_config.max_height = 8096;
	ddev->mode_config.normalize_zpos = true;
	ddev->mode_config.funcs = &mode_config_funcs;
	ddev->mode_config.helper_private = &mode_config_helper_funcs;

	ret = tidss_dispc_modeset_init(tidss);
	if (ret)
		return ret;

	ret = drm_vblank_init(ddev, tidss->num_crtcs);
	if (ret)
		return ret;

	/* Start with vertical blanking interrupt reporting disabled. */
	for (i = 0; i < tidss->num_crtcs; ++i)
		drm_crtc_vblank_reset(tidss->crtcs[i]);

	drm_mode_config_reset(ddev);

	dev_dbg(tidss->dev, "%s done\n", __func__);

	return 0;
}
