// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 */

#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>

#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>

struct display_connector {
	struct drm_bridge	bridge;

	struct gpio_desc	*hpd_gpio;
	int			hpd_irq;
};

static inline struct display_connector *
to_display_connector(struct drm_bridge *bridge)
{
	return container_of(bridge, struct display_connector, bridge);
}

static int display_connector_attach(struct drm_bridge *bridge,
				    enum drm_bridge_attach_flags flags)
{
	return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
}

static enum drm_connector_status
display_connector_detect(struct drm_bridge *bridge)
{
	struct display_connector *conn = to_display_connector(bridge);

	if (conn->hpd_gpio) {
		if (gpiod_get_value_cansleep(conn->hpd_gpio))
			return connector_status_connected;
		else
			return connector_status_disconnected;
	}

	if (conn->bridge.ddc && drm_probe_ddc(conn->bridge.ddc))
		return connector_status_connected;

	switch (conn->bridge.type) {
	case DRM_MODE_CONNECTOR_DVIA:
	case DRM_MODE_CONNECTOR_DVID:
	case DRM_MODE_CONNECTOR_DVII:
	case DRM_MODE_CONNECTOR_HDMIA:
	case DRM_MODE_CONNECTOR_HDMIB:
		/*
		 * For DVI and HDMI connectors a DDC probe failure indicates
		 * that no cable is connected.
		 */
		return connector_status_disconnected;

	case DRM_MODE_CONNECTOR_Composite:
	case DRM_MODE_CONNECTOR_SVIDEO:
	case DRM_MODE_CONNECTOR_VGA:
	default:
		/*
		 * Composite and S-Video connectors have no other detection
		 * mean than the HPD GPIO. For VGA connectors, even if we have
		 * an I2C bus, we can't assume that the cable is disconnected
		 * if drm_probe_ddc fails, as some cables don't wire the DDC
		 * pins.
		 */
		return connector_status_unknown;
	}
}

static struct edid *display_connector_get_edid(struct drm_bridge *bridge,
					       struct drm_connector *connector)
{
	struct display_connector *conn = to_display_connector(bridge);

	return drm_get_edid(connector, conn->bridge.ddc);
}

static const struct drm_bridge_funcs display_connector_bridge_funcs = {
	.attach = display_connector_attach,
	.detect = display_connector_detect,
	.get_edid = display_connector_get_edid,
};

static irqreturn_t display_connector_hpd_irq(int irq, void *arg)
{
	struct display_connector *conn = arg;
	struct drm_bridge *bridge = &conn->bridge;

	drm_bridge_hpd_notify(bridge, display_connector_detect(bridge));

	return IRQ_HANDLED;
}

static int display_connector_probe(struct platform_device *pdev)
{
	struct display_connector *conn;
	unsigned int type;
	const char *label = NULL;
	int ret;

	conn = devm_kzalloc(&pdev->dev, sizeof(*conn), GFP_KERNEL);
	if (!conn)
		return -ENOMEM;

	platform_set_drvdata(pdev, conn);

	type = (uintptr_t)of_device_get_match_data(&pdev->dev);

	/* Get the exact connector type. */
	switch (type) {
	case DRM_MODE_CONNECTOR_DVII: {
		bool analog, digital;

		analog = of_property_read_bool(pdev->dev.of_node, "analog");
		digital = of_property_read_bool(pdev->dev.of_node, "digital");
		if (analog && !digital) {
			conn->bridge.type = DRM_MODE_CONNECTOR_DVIA;
		} else if (!analog && digital) {
			conn->bridge.type = DRM_MODE_CONNECTOR_DVID;
		} else if (analog && digital) {
			conn->bridge.type = DRM_MODE_CONNECTOR_DVII;
		} else {
			dev_err(&pdev->dev, "DVI connector with no type\n");
			return -EINVAL;
		}
		break;
	}

	case DRM_MODE_CONNECTOR_HDMIA: {
		const char *hdmi_type;

		ret = of_property_read_string(pdev->dev.of_node, "type",
					      &hdmi_type);
		if (ret < 0) {
			dev_err(&pdev->dev, "HDMI connector with no type\n");
			return -EINVAL;
		}

		if (!strcmp(hdmi_type, "a") || !strcmp(hdmi_type, "c") ||
		    !strcmp(hdmi_type, "d") || !strcmp(hdmi_type, "e")) {
			conn->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
		} else if (!strcmp(hdmi_type, "b")) {
			conn->bridge.type = DRM_MODE_CONNECTOR_HDMIB;
		} else {
			dev_err(&pdev->dev,
				"Unsupported HDMI connector type '%s'\n",
				hdmi_type);
			return -EINVAL;
		}

		break;
	}

	default:
		conn->bridge.type = type;
		break;
	}

	/* All the supported connector types support interlaced modes. */
	conn->bridge.interlace_allowed = true;

	/* Get the optional connector label. */
	of_property_read_string(pdev->dev.of_node, "label", &label);

	/*
	 * Get the HPD GPIO for DVI and HDMI connectors. If the GPIO can provide
	 * edge interrupts, register an interrupt handler.
	 */
	if (type == DRM_MODE_CONNECTOR_DVII ||
	    type == DRM_MODE_CONNECTOR_HDMIA) {
		conn->hpd_gpio = devm_gpiod_get_optional(&pdev->dev, "hpd",
							 GPIOD_IN);
		if (IS_ERR(conn->hpd_gpio)) {
			if (PTR_ERR(conn->hpd_gpio) != -EPROBE_DEFER)
				dev_err(&pdev->dev,
					"Unable to retrieve HPD GPIO\n");
			return PTR_ERR(conn->hpd_gpio);
		}

		conn->hpd_irq = gpiod_to_irq(conn->hpd_gpio);
	} else {
		conn->hpd_irq = -EINVAL;
	}

	if (conn->hpd_irq >= 0) {
		ret = devm_request_threaded_irq(&pdev->dev, conn->hpd_irq,
						NULL, display_connector_hpd_irq,
						IRQF_TRIGGER_RISING |
						IRQF_TRIGGER_FALLING |
						IRQF_ONESHOT,
						"HPD", conn);
		if (ret) {
			dev_info(&pdev->dev,
				 "Failed to request HPD edge interrupt, falling back to polling\n");
			conn->hpd_irq = -EINVAL;
		}
	}

	/* Retrieve the DDC I2C adapter for DVI, HDMI and VGA connectors. */
	if (type == DRM_MODE_CONNECTOR_DVII ||
	    type == DRM_MODE_CONNECTOR_HDMIA ||
	    type == DRM_MODE_CONNECTOR_VGA) {
		struct device_node *phandle;

		phandle = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
		if (phandle) {
			conn->bridge.ddc = of_get_i2c_adapter_by_node(phandle);
			of_node_put(phandle);
			if (!conn->bridge.ddc)
				return -EPROBE_DEFER;
		} else {
			dev_dbg(&pdev->dev,
				"No I2C bus specified, disabling EDID readout\n");
		}
	}

	conn->bridge.funcs = &display_connector_bridge_funcs;
	conn->bridge.of_node = pdev->dev.of_node;

	if (conn->bridge.ddc)
		conn->bridge.ops |= DRM_BRIDGE_OP_EDID
				 |  DRM_BRIDGE_OP_DETECT;
	if (conn->hpd_gpio)
		conn->bridge.ops |= DRM_BRIDGE_OP_DETECT;
	if (conn->hpd_irq >= 0)
		conn->bridge.ops |= DRM_BRIDGE_OP_HPD;

	dev_dbg(&pdev->dev,
		"Found %s display connector '%s' %s DDC bus and %s HPD GPIO (ops 0x%x)\n",
		drm_get_connector_type_name(conn->bridge.type),
		label ? label : "<unlabelled>",
		conn->bridge.ddc ? "with" : "without",
		conn->hpd_gpio ? "with" : "without",
		conn->bridge.ops);

	drm_bridge_add(&conn->bridge);

	return 0;
}

static int display_connector_remove(struct platform_device *pdev)
{
	struct display_connector *conn = platform_get_drvdata(pdev);

	drm_bridge_remove(&conn->bridge);

	if (!IS_ERR(conn->bridge.ddc))
		i2c_put_adapter(conn->bridge.ddc);

	return 0;
}

static const struct of_device_id display_connector_match[] = {
	{
		.compatible = "composite-video-connector",
		.data = (void *)DRM_MODE_CONNECTOR_Composite,
	}, {
		.compatible = "dvi-connector",
		.data = (void *)DRM_MODE_CONNECTOR_DVII,
	}, {
		.compatible = "hdmi-connector",
		.data = (void *)DRM_MODE_CONNECTOR_HDMIA,
	}, {
		.compatible = "svideo-connector",
		.data = (void *)DRM_MODE_CONNECTOR_SVIDEO,
	}, {
		.compatible = "vga-connector",
		.data = (void *)DRM_MODE_CONNECTOR_VGA,
	},
	{},
};
MODULE_DEVICE_TABLE(of, display_connector_match);

static struct platform_driver display_connector_driver = {
	.probe	= display_connector_probe,
	.remove	= display_connector_remove,
	.driver		= {
		.name		= "display-connector",
		.of_match_table	= display_connector_match,
	},
};
module_platform_driver(display_connector_driver);

MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
MODULE_DESCRIPTION("Display connector driver");
MODULE_LICENSE("GPL");
