/*
 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
 * Author: Rob Clark <rob@ti.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/list.h>

#include <drm/drm_crtc.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_edid.h>

#include "omap_drv.h"

/*
 * encoder funcs
 */

#define to_omap_encoder(x) container_of(x, struct omap_encoder, base)

/* The encoder and connector both map to same dssdev.. the encoder
 * handles the 'active' parts, ie. anything the modifies the state
 * of the hw, and the connector handles the 'read-only' parts, like
 * detecting connection and reading edid.
 */
struct omap_encoder {
	struct drm_encoder base;
	struct omap_dss_device *output;
	struct omap_dss_device *display;
};

static void omap_encoder_destroy(struct drm_encoder *encoder)
{
	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);

	drm_encoder_cleanup(encoder);
	kfree(omap_encoder);
}

static const struct drm_encoder_funcs omap_encoder_funcs = {
	.destroy = omap_encoder_destroy,
};

static void omap_encoder_hdmi_mode_set(struct drm_encoder *encoder,
				       struct drm_display_mode *adjusted_mode)
{
	struct drm_device *dev = encoder->dev;
	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
	struct omap_dss_device *dssdev = omap_encoder->output;
	struct drm_connector *connector;
	bool hdmi_mode;

	hdmi_mode = false;
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
		if (connector->encoder == encoder) {
			hdmi_mode = omap_connector_get_hdmi_mode(connector);
			break;
		}
	}

	if (dssdev->ops->hdmi.set_hdmi_mode)
		dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);

	if (hdmi_mode && dssdev->ops->hdmi.set_infoframe) {
		struct hdmi_avi_infoframe avi;
		int r;

		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector,
							     adjusted_mode);
		if (r == 0)
			dssdev->ops->hdmi.set_infoframe(dssdev, &avi);
	}
}

static void omap_encoder_mode_set(struct drm_encoder *encoder,
				  struct drm_display_mode *mode,
				  struct drm_display_mode *adjusted_mode)
{
	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
	struct omap_dss_device *dssdev;
	struct videomode vm = { 0 };

	drm_display_mode_to_videomode(adjusted_mode, &vm);

	/*
	 * HACK: This fixes the vm flags.
	 * struct drm_display_mode does not contain the VSYNC/HSYNC/DE flags and
	 * they get lost when converting back and forth between struct
	 * drm_display_mode and struct videomode. The hack below goes and
	 * fetches the missing flags.
	 *
	 * A better solution is to use DRM's bus-flags through the whole driver.
	 */
	for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) {
		unsigned long bus_flags = dssdev->bus_flags;

		if (!(vm.flags & (DISPLAY_FLAGS_DE_LOW |
				  DISPLAY_FLAGS_DE_HIGH))) {
			if (bus_flags & DRM_BUS_FLAG_DE_LOW)
				vm.flags |= DISPLAY_FLAGS_DE_LOW;
			else if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
				vm.flags |= DISPLAY_FLAGS_DE_HIGH;
		}

		if (!(vm.flags & (DISPLAY_FLAGS_PIXDATA_POSEDGE |
				  DISPLAY_FLAGS_PIXDATA_NEGEDGE))) {
			if (bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE)
				vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
			else if (bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
				vm.flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
		}

		if (!(vm.flags & (DISPLAY_FLAGS_SYNC_POSEDGE |
				  DISPLAY_FLAGS_SYNC_NEGEDGE))) {
			if (bus_flags & DRM_BUS_FLAG_SYNC_POSEDGE)
				vm.flags |= DISPLAY_FLAGS_SYNC_POSEDGE;
			else if (bus_flags & DRM_BUS_FLAG_SYNC_NEGEDGE)
				vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
		}
	}

	/* Set timings for all devices in the display pipeline. */
	dss_mgr_set_timings(omap_encoder->output, &vm);

	for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) {
		if (dssdev->ops->set_timings)
			dssdev->ops->set_timings(dssdev, &vm);
	}

	/* Set the HDMI mode and HDMI infoframe if applicable. */
	if (omap_encoder->output->output_type == OMAP_DISPLAY_TYPE_HDMI)
		omap_encoder_hdmi_mode_set(encoder, adjusted_mode);
}

static void omap_encoder_disable(struct drm_encoder *encoder)
{
	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
	struct omap_dss_device *dssdev = omap_encoder->display;

	dssdev->ops->disable(dssdev);
}

static void omap_encoder_enable(struct drm_encoder *encoder)
{
	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
	struct omap_dss_device *dssdev = omap_encoder->display;
	int r;

	r = dssdev->ops->enable(dssdev);
	if (r)
		dev_err(encoder->dev->dev,
			"Failed to enable display '%s': %d\n",
			dssdev->name, r);
}

static int omap_encoder_atomic_check(struct drm_encoder *encoder,
				     struct drm_crtc_state *crtc_state,
				     struct drm_connector_state *conn_state)
{
	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
	enum omap_channel channel = omap_encoder->output->dispc_channel;
	struct drm_device *dev = encoder->dev;
	struct omap_drm_private *priv = dev->dev_private;
	struct omap_dss_device *dssdev;
	struct videomode vm = { 0 };
	int ret;

	drm_display_mode_to_videomode(&crtc_state->mode, &vm);

	ret = priv->dispc_ops->mgr_check_timings(priv->dispc, channel, &vm);
	if (ret)
		goto done;

	for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) {
		if (!dssdev->ops->check_timings)
			continue;

		ret = dssdev->ops->check_timings(dssdev, &vm);
		if (ret)
			goto done;
	}

	drm_display_mode_from_videomode(&vm, &crtc_state->adjusted_mode);

done:
	if (ret)
		dev_err(dev->dev, "invalid timings: %d\n", ret);

	return ret;
}

static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
	.mode_set = omap_encoder_mode_set,
	.disable = omap_encoder_disable,
	.enable = omap_encoder_enable,
	.atomic_check = omap_encoder_atomic_check,
};

/* initialize encoder */
struct drm_encoder *omap_encoder_init(struct drm_device *dev,
				      struct omap_dss_device *output,
				      struct omap_dss_device *display)
{
	struct drm_encoder *encoder = NULL;
	struct omap_encoder *omap_encoder;

	omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
	if (!omap_encoder)
		goto fail;

	omap_encoder->output = output;
	omap_encoder->display = display;

	encoder = &omap_encoder->base;

	drm_encoder_init(dev, encoder, &omap_encoder_funcs,
			 DRM_MODE_ENCODER_TMDS, NULL);
	drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);

	return encoder;

fail:
	if (encoder)
		omap_encoder_destroy(encoder);

	return NULL;
}
