// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2017 NXP Semiconductors.
 * Author: Marco Franchi <marco.franchi@nxp.com>
 *
 * Based on Panel Simple driver by Thierry Reding <treding@nvidia.com>
 */

#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>

#include <video/display_timing.h>
#include <video/videomode.h>

#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
#include <drm/drm_panel.h>

struct seiko_panel_desc {
	const struct drm_display_mode *modes;
	unsigned int num_modes;
	const struct display_timing *timings;
	unsigned int num_timings;

	unsigned int bpc;

	/**
	 * @width: width (in millimeters) of the panel's active display area
	 * @height: height (in millimeters) of the panel's active display area
	 */
	struct {
		unsigned int width;
		unsigned int height;
	} size;

	u32 bus_format;
	u32 bus_flags;
};

struct seiko_panel {
	struct drm_panel base;
	bool prepared;
	bool enabled;
	const struct seiko_panel_desc *desc;
	struct regulator *dvdd;
	struct regulator *avdd;
};

static inline struct seiko_panel *to_seiko_panel(struct drm_panel *panel)
{
	return container_of(panel, struct seiko_panel, base);
}

static int seiko_panel_get_fixed_modes(struct seiko_panel *panel,
				       struct drm_connector *connector)
{
	struct drm_display_mode *mode;
	unsigned int i, num = 0;

	if (!panel->desc)
		return 0;

	for (i = 0; i < panel->desc->num_timings; i++) {
		const struct display_timing *dt = &panel->desc->timings[i];
		struct videomode vm;

		videomode_from_timing(dt, &vm);
		mode = drm_mode_create(connector->dev);
		if (!mode) {
			dev_err(panel->base.dev, "failed to add mode %ux%u\n",
				dt->hactive.typ, dt->vactive.typ);
			continue;
		}

		drm_display_mode_from_videomode(&vm, mode);

		mode->type |= DRM_MODE_TYPE_DRIVER;

		if (panel->desc->num_timings == 1)
			mode->type |= DRM_MODE_TYPE_PREFERRED;

		drm_mode_probed_add(connector, mode);
		num++;
	}

	for (i = 0; i < panel->desc->num_modes; i++) {
		const struct drm_display_mode *m = &panel->desc->modes[i];

		mode = drm_mode_duplicate(connector->dev, m);
		if (!mode) {
			dev_err(panel->base.dev, "failed to add mode %ux%u@%u\n",
				m->hdisplay, m->vdisplay,
				drm_mode_vrefresh(m));
			continue;
		}

		mode->type |= DRM_MODE_TYPE_DRIVER;

		if (panel->desc->num_modes == 1)
			mode->type |= DRM_MODE_TYPE_PREFERRED;

		drm_mode_set_name(mode);

		drm_mode_probed_add(connector, mode);
		num++;
	}

	connector->display_info.bpc = panel->desc->bpc;
	connector->display_info.width_mm = panel->desc->size.width;
	connector->display_info.height_mm = panel->desc->size.height;
	if (panel->desc->bus_format)
		drm_display_info_set_bus_formats(&connector->display_info,
						 &panel->desc->bus_format, 1);
	connector->display_info.bus_flags = panel->desc->bus_flags;

	return num;
}

static int seiko_panel_disable(struct drm_panel *panel)
{
	struct seiko_panel *p = to_seiko_panel(panel);

	if (!p->enabled)
		return 0;

	p->enabled = false;

	return 0;
}

static int seiko_panel_unprepare(struct drm_panel *panel)
{
	struct seiko_panel *p = to_seiko_panel(panel);

	if (!p->prepared)
		return 0;

	regulator_disable(p->avdd);

	/* Add a 100ms delay as per the panel datasheet */
	msleep(100);

	regulator_disable(p->dvdd);

	p->prepared = false;

	return 0;
}

static int seiko_panel_prepare(struct drm_panel *panel)
{
	struct seiko_panel *p = to_seiko_panel(panel);
	int err;

	if (p->prepared)
		return 0;

	err = regulator_enable(p->dvdd);
	if (err < 0) {
		dev_err(panel->dev, "failed to enable dvdd: %d\n", err);
		return err;
	}

	/* Add a 100ms delay as per the panel datasheet */
	msleep(100);

	err = regulator_enable(p->avdd);
	if (err < 0) {
		dev_err(panel->dev, "failed to enable avdd: %d\n", err);
		goto disable_dvdd;
	}

	p->prepared = true;

	return 0;

disable_dvdd:
	regulator_disable(p->dvdd);
	return err;
}

static int seiko_panel_enable(struct drm_panel *panel)
{
	struct seiko_panel *p = to_seiko_panel(panel);

	if (p->enabled)
		return 0;

	p->enabled = true;

	return 0;
}

static int seiko_panel_get_modes(struct drm_panel *panel,
				 struct drm_connector *connector)
{
	struct seiko_panel *p = to_seiko_panel(panel);

	/* add hard-coded panel modes */
	return seiko_panel_get_fixed_modes(p, connector);
}

static int seiko_panel_get_timings(struct drm_panel *panel,
				    unsigned int num_timings,
				    struct display_timing *timings)
{
	struct seiko_panel *p = to_seiko_panel(panel);
	unsigned int i;

	if (p->desc->num_timings < num_timings)
		num_timings = p->desc->num_timings;

	if (timings)
		for (i = 0; i < num_timings; i++)
			timings[i] = p->desc->timings[i];

	return p->desc->num_timings;
}

static const struct drm_panel_funcs seiko_panel_funcs = {
	.disable = seiko_panel_disable,
	.unprepare = seiko_panel_unprepare,
	.prepare = seiko_panel_prepare,
	.enable = seiko_panel_enable,
	.get_modes = seiko_panel_get_modes,
	.get_timings = seiko_panel_get_timings,
};

static int seiko_panel_probe(struct device *dev,
					const struct seiko_panel_desc *desc)
{
	struct seiko_panel *panel;
	int err;

	panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
	if (!panel)
		return -ENOMEM;

	panel->enabled = false;
	panel->prepared = false;
	panel->desc = desc;

	panel->dvdd = devm_regulator_get(dev, "dvdd");
	if (IS_ERR(panel->dvdd))
		return PTR_ERR(panel->dvdd);

	panel->avdd = devm_regulator_get(dev, "avdd");
	if (IS_ERR(panel->avdd))
		return PTR_ERR(panel->avdd);

	drm_panel_init(&panel->base, dev, &seiko_panel_funcs,
		       DRM_MODE_CONNECTOR_DPI);

	err = drm_panel_of_backlight(&panel->base);
	if (err)
		return err;

	drm_panel_add(&panel->base);

	dev_set_drvdata(dev, panel);

	return 0;
}

static int seiko_panel_remove(struct platform_device *pdev)
{
	struct seiko_panel *panel = dev_get_drvdata(&pdev->dev);

	drm_panel_remove(&panel->base);
	drm_panel_disable(&panel->base);

	return 0;
}

static void seiko_panel_shutdown(struct platform_device *pdev)
{
	struct seiko_panel *panel = dev_get_drvdata(&pdev->dev);

	drm_panel_disable(&panel->base);
}

static const struct display_timing seiko_43wvf1g_timing = {
	.pixelclock = { 33500000, 33500000, 33500000 },
	.hactive = { 800, 800, 800 },
	.hfront_porch = {  164, 164, 164 },
	.hback_porch = { 89, 89, 89 },
	.hsync_len = { 10, 10, 10 },
	.vactive = { 480, 480, 480 },
	.vfront_porch = { 10, 10, 10 },
	.vback_porch = { 23, 23, 23 },
	.vsync_len = { 10, 10, 10 },
	.flags = DISPLAY_FLAGS_DE_LOW,
};

static const struct seiko_panel_desc seiko_43wvf1g = {
	.timings = &seiko_43wvf1g_timing,
	.num_timings = 1,
	.bpc = 8,
	.size = {
		.width = 93,
		.height = 57,
	},
	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
};

static const struct of_device_id platform_of_match[] = {
	{
		.compatible = "sii,43wvf1g",
		.data = &seiko_43wvf1g,
	}, {
		/* sentinel */
	}
};
MODULE_DEVICE_TABLE(of, platform_of_match);

static int seiko_panel_platform_probe(struct platform_device *pdev)
{
	const struct of_device_id *id;

	id = of_match_node(platform_of_match, pdev->dev.of_node);
	if (!id)
		return -ENODEV;

	return seiko_panel_probe(&pdev->dev, id->data);
}

static struct platform_driver seiko_panel_platform_driver = {
	.driver = {
		.name = "seiko_panel",
		.of_match_table = platform_of_match,
	},
	.probe = seiko_panel_platform_probe,
	.remove = seiko_panel_remove,
	.shutdown = seiko_panel_shutdown,
};
module_platform_driver(seiko_panel_platform_driver);

MODULE_AUTHOR("Marco Franchi <marco.franchi@nxp.com>");
MODULE_DESCRIPTION("Seiko 43WVF1G panel driver");
MODULE_LICENSE("GPL v2");
