All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rahul Sharma <rahul.sharma@samsung.com>
To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
	linux-samsung-soc@vger.kernel.org,
	dri-devel@lists.freedesktop.org
Cc: kgene.kim@samsung.com, sw0312.kim@samsung.com,
	inki.dae@samsung.com, seanpaul@chromium.org,
	tomasz.figa@gmail.com, s.nawrocki@samsung.com, joshi@samsung.com,
	r.sh.open@gmail.com, Rahul Sharma <rahul.sharma@samsung.com>
Subject: [PATCH v2 3/7] drm/exynos: add hdmiphy platform driver for exynos5420
Date: Tue, 22 Oct 2013 15:41:04 +0530	[thread overview]
Message-ID: <1382436668-15813-4-git-send-email-rahul.sharma@samsung.com> (raw)
In-Reply-To: <1382436668-15813-1-git-send-email-rahul.sharma@samsung.com>

Exynos5420 hdmiphy device is a platform device, unlike
predecessor SoCs where it used to be a I2C device. This
support is added to the hdmiphy platform driver.

Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
---
 drivers/gpu/drm/exynos/Makefile                  |    1 +
 drivers/gpu/drm/exynos/exynos_hdmi.c             |   61 +++-
 drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c |  363 ++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h     |    1 +
 4 files changed, 413 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c

diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 463239b..eedd145 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -13,6 +13,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)	+= exynos_drm_fimd.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o exynos_mixer.o \
 					   exynos_ddc.o exynos_hdmiphy_i2c.o \
+					   exynos_hdmiphy_platform.o \
 					   exynos_drm_hdmi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)	+= exynos_drm_vidi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)	+= exynos_drm_g2d.o
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 444541d..e199d7d 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -35,6 +35,7 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_i2c.h>
+#include <linux/of_platform.h>
 
 #include <drm/exynos_drm.h>
 
@@ -1608,10 +1609,14 @@ static int hdmi_register_phy_device(struct hdmi_context *hdata, bool i2c_dev)
 {
 	struct device_node *np;
 	struct i2c_client *client;
+	struct platform_device *pdev;
 	int ret;
 
 	/* register hdmiphy driver */
-	ret = exynos_hdmiphy_i2c_driver_register();
+	if (i2c_dev)
+		ret = exynos_hdmiphy_i2c_driver_register();
+	else
+		ret = exynos_hdmiphy_platform_driver_register();
 	if (ret) {
 		DRM_ERROR("failed to register phy driver. ret %d.\n", ret);
 		goto err;
@@ -1624,16 +1629,29 @@ static int hdmi_register_phy_device(struct hdmi_context *hdata, bool i2c_dev)
 		goto err;
 	}
 
-	/* find hdmi phy on i2c bus */
-	client = of_find_i2c_device_by_node(np);
-	if (!client) {
-		DRM_ERROR("Could not find i2c 'phy' device\n");
-		ret = -ENODEV;
-		goto err;
+	if (i2c_dev) {
+		/* find hdmi phy on i2c bus */
+		client = of_find_i2c_device_by_node(np);
+		if (!client) {
+			DRM_ERROR("Could not find i2c 'phy' device\n");
+			ret = -ENODEV;
+			goto err;
+		}
+		hdata->phy_dev = &client->dev;
+		hdata->phy_ops = exynos_hdmiphy_i2c_device_get_ops(
+					hdata->phy_dev);
+	} else {
+		/* find hdmi phy on platform bus */
+		pdev = of_find_device_by_node(np);
+		if (!pdev) {
+			DRM_ERROR("Could not find platform 'phy' device\n");
+			ret = -ENODEV;
+			goto err;
+		}
+		hdata->phy_dev = &pdev->dev;
+		hdata->phy_ops = exynos_hdmiphy_platform_device_get_ops(
+					hdata->phy_dev);
 	}
-	hdata->phy_dev = &client->dev;
-	hdata->phy_ops = exynos_hdmiphy_i2c_device_get_ops(
-				hdata->phy_dev);
 
 	if (!hdata->phy_ops) {
 		ret = -EINVAL;
@@ -1652,6 +1670,11 @@ static struct hdmi_drv_data exynos5250_hdmi_drv_data = {
 	.i2c_hdmiphy = 1,
 };
 
+static struct hdmi_drv_data exynos5420_hdmi_drv_data = {
+	.type = HDMI_TYPE14,
+	.i2c_hdmiphy = 0,
+};
+
 static struct of_device_id hdmi_match_types[] = {
 	{
 		.compatible = "samsung,exynos5-hdmi",
@@ -1660,6 +1683,9 @@ static struct of_device_id hdmi_match_types[] = {
 		.compatible = "samsung,exynos4212-hdmi",
 		.data	= &exynos5250_hdmi_drv_data,
 	}, {
+		.compatible = "samsung,exynos5420-hdmi",
+		.data	= &exynos5420_hdmi_drv_data,
+	}, {
 		/* end node */
 	}
 };
@@ -1767,7 +1793,10 @@ static int hdmi_probe(struct platform_device *pdev)
 	return 0;
 
 err_hdmiphy:
-	exynos_hdmiphy_i2c_driver_unregister();
+	if (drv->i2c_hdmiphy)
+		exynos_hdmiphy_i2c_driver_unregister();
+	else
+		exynos_hdmiphy_platform_driver_unregister();
 err_ddc:
 	i2c_del_driver(&ddc_driver);
 	return ret;
@@ -1776,11 +1805,17 @@ err_ddc:
 static int hdmi_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
+	struct hdmi_context *hdata = ctx->ctx;
 
 	pm_runtime_disable(dev);
 
-	/* hdmiphy i2c driver */
-	exynos_hdmiphy_i2c_driver_unregister();
+	/* hdmiphy driver */
+	if (i2c_verify_client(hdata->phy_dev))
+		exynos_hdmiphy_i2c_driver_unregister();
+	else
+		exynos_hdmiphy_platform_driver_unregister();
+
 	/* DDC i2c driver */
 	i2c_del_driver(&ddc_driver);
 
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c b/drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c
new file mode 100644
index 0000000..053d854
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co.Ltd
+ * Authors:
+ *	Rahul Sharma <rahul.sharma@samsung.com>
+ *
+ * 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.
+ *
+ */
+#include <drm/drmP.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "regs-hdmiphy.h"
+#include "exynos_hdmiphy.h"
+#include "exynos_hdmiphy_priv.h"
+
+/* default phy config settings for exynos5420 */
+static struct hdmiphy_config hdmiphy_5420_configs[] = {
+	{
+		.pixel_clock = 25200000,
+		.conf = {
+			0x52, 0x3F, 0x55, 0x40, 0x01, 0x00, 0xC8, 0x82,
+			0xC8, 0xBD, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x06,
+			0x80, 0x01, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xF4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 27000000,
+		.conf = {
+			0xD1, 0x22, 0x51, 0x40, 0x08, 0xFC, 0xE0, 0x98,
+			0xE8, 0xCB, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x06,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xE4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 27027000,
+		.conf = {
+			0xD1, 0x2D, 0x72, 0x40, 0x64, 0x12, 0xC8, 0x43,
+			0xE8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x06,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xE3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 36000000,
+		.conf = {
+			0x51, 0x2D, 0x55, 0x40, 0x40, 0x00, 0xC8, 0x02,
+			0xC8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xAB, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 40000000,
+		.conf = {
+			0xD1, 0x21, 0x31, 0x40, 0x3C, 0x28, 0xC8, 0x87,
+			0xE8, 0xC8, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x9A, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 65000000,
+		.conf = {
+			0xD1, 0x36, 0x34, 0x40, 0x0C, 0x04, 0xC8, 0x82,
+			0xE8, 0x45, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xBD, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 71000000,
+		.conf = {
+			0xD1, 0x3B, 0x35, 0x40, 0x0C, 0x04, 0xC8, 0x85,
+			0xE8, 0x63, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x57, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 74176000,
+		.conf = {
+			0xD1, 0x1F, 0x10, 0x40, 0x5B, 0xEF, 0xC8, 0x81,
+			0xE8, 0xB9, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x56,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xA6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 74250000,
+		.conf = {
+			0xD1, 0x1F, 0x10, 0x40, 0x40, 0xF8, 0xC8, 0x81,
+			0xE8, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x56,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xA5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 83500000,
+		.conf = {
+			0xD1, 0x23, 0x11, 0x40, 0x0C, 0xFB, 0xC8, 0x85,
+			0xE8, 0xD1, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x4A, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 106500000,
+		.conf = {
+			0xD1, 0x2C, 0x12, 0x40, 0x0C, 0x09, 0xC8, 0x84,
+			0xE8, 0x0A, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 108000000,
+		.conf = {
+			0x51, 0x2D, 0x15, 0x40, 0x01, 0x00, 0xC8, 0x82,
+			0xC8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xC7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 146250000,
+		.conf = {
+			0xD1, 0x3D, 0x15, 0x40, 0x18, 0xFD, 0xC8, 0x83,
+			0xE8, 0x6E, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x54, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 148500000,
+		.conf = {
+			0xD1, 0x1F, 0x00, 0x40, 0x40, 0xF8, 0xC8, 0x81,
+			0xE8, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x66,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x4B, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+};
+
+static struct hdmiphy_config *hdmiphy_find_conf(struct hdmiphy_context *hdata,
+			unsigned int pixel_clk)
+{
+	int i;
+
+	for (i = 0; i < hdata->nr_confs; i++)
+		if (hdata->confs[i].pixel_clock == pixel_clk)
+			return &hdata->confs[i];
+
+	return NULL;
+}
+
+static int hdmiphy_reg_writeb(struct hdmiphy_context *hdata,
+			u32 reg_offset, u8 value)
+{
+	if (reg_offset >= HDMIPHY_REG_COUNT)
+		return -EINVAL;
+
+	writeb(value, hdata->regs + (reg_offset<<2));
+	return 0;
+}
+
+static int hdmiphy_reg_write_buf(struct hdmiphy_context *hdata,
+			u32 reg_offset, const u8 *buf, u32 len)
+{
+	int i;
+
+	if ((reg_offset + len) > HDMIPHY_REG_COUNT)
+		return -EINVAL;
+
+	for (i = 0; i < len; i++)
+		writeb(buf[i], hdata->regs +
+			((reg_offset + i)<<2));
+	return 0;
+}
+
+static int hdmiphy_check_mode(struct device *dev,
+			struct drm_display_mode *mode)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+	const struct hdmiphy_config *conf;
+
+	DRM_DEBUG("%s xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
+		__func__, mode->hdisplay, mode->vdisplay,
+		mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		? true : false, mode->clock * 1000);
+
+	conf = hdmiphy_find_conf(hdata, mode->clock * 1000);
+	if (!conf) {
+		DRM_DEBUG("Display Mode is not supported.\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int hdmiphy_mode_set(struct device *dev,
+			struct drm_display_mode *mode)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	hdata->current_conf = hdmiphy_find_conf(hdata, mode->clock * 1000);
+	if (!hdata->current_conf) {
+		DRM_ERROR("Display Mode is not supported.\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int hdmiphy_commit(struct device *dev)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+	int ret;
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	ret = hdmiphy_reg_write_buf(hdata, 1, hdata->current_conf->conf,
+			HDMIPHY_REG_COUNT - 1);
+	if (ret) {
+		DRM_ERROR("failed to configure hdmiphy. ret %d.\n", ret);
+		return ret;
+	}
+
+	/* need this delay before phy can be set to operation. */
+	usleep_range(10000, 12000);
+	return 0;
+}
+
+static void hdmiphy_enable(struct device *dev, int enable)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	if (enable)
+		hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
+				HDMIPHY_MODE_EN);
+	else
+		hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE, 0);
+}
+
+static void hdmiphy_poweron(struct device *dev, int mode)
+{
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+}
+
+struct exynos_hdmiphy_ops *exynos_hdmiphy_platform_device_get_ops
+			(struct device *dev)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	if (hdata)
+		return hdata->ops;
+
+	return NULL;
+}
+
+static struct exynos_hdmiphy_ops phy_ops = {
+	.check_mode = hdmiphy_check_mode,
+	.mode_set = hdmiphy_mode_set,
+	.commit = hdmiphy_commit,
+	.enable = hdmiphy_enable,
+	.poweron = hdmiphy_poweron,
+};
+
+static struct hdmiphy_drv_data exynos5420_hdmiphy_drv_data = {
+	.confs = hdmiphy_5420_configs,
+	.count = ARRAY_SIZE(hdmiphy_5420_configs)
+};
+
+static struct of_device_id hdmiphy_platform_device_match_types[] = {
+	{
+		.compatible = "samsung,exynos5420-hdmiphy",
+		.data	= &exynos5420_hdmiphy_drv_data,
+	}, {
+		/* end node */
+	}
+};
+
+static int hdmiphy_platform_device_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct hdmiphy_context *hdata;
+	struct hdmiphy_drv_data *drv;
+	struct resource *res;
+	const struct of_device_id *match;
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	hdata = devm_kzalloc(dev, sizeof(*hdata), GFP_KERNEL);
+	if (!hdata) {
+		DRM_ERROR("failed to allocate hdmiphy context.\n");
+		return -ENOMEM;
+	}
+
+	match = of_match_node(of_match_ptr(
+		hdmiphy_platform_device_match_types),
+		dev->of_node);
+
+	if (!match)
+		return -ENODEV;
+
+	drv = (struct hdmiphy_drv_data *)match->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		DRM_ERROR("failed to find phy registers\n");
+		return -ENOENT;
+	}
+
+	hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
+	if (!hdata->regs) {
+		DRM_ERROR("failed to map registers\n");
+		return -ENXIO;
+	}
+
+	hdata->confs = drv->confs;
+	hdata->nr_confs = drv->count;
+	hdata->ops = &phy_ops;
+
+	platform_set_drvdata(pdev, hdata);
+	return 0;
+}
+
+struct platform_driver hdmiphy_platform_driver = {
+	.driver = {
+		.name	= "exynos-hdmiphy",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(
+				hdmiphy_platform_device_match_types),
+	},
+	.probe		= hdmiphy_platform_device_probe,
+};
+
+int exynos_hdmiphy_platform_driver_register(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&hdmiphy_platform_driver);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+void exynos_hdmiphy_platform_driver_unregister(void)
+{
+	platform_driver_unregister(&hdmiphy_platform_driver);
+}
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h b/drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h
index 4948c81..9ba46d4 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h
+++ b/drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h
@@ -15,6 +15,7 @@
 
 struct hdmiphy_context {
 	/* hdmiphy resources */
+	void __iomem		*regs;
 	struct exynos_hdmiphy_ops	*ops;
 	struct hdmiphy_config	*confs;
 	unsigned int		nr_confs;
-- 
1.7.10.4

WARNING: multiple messages have this Message-ID (diff)
From: rahul.sharma@samsung.com (Rahul Sharma)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 3/7] drm/exynos: add hdmiphy platform driver for exynos5420
Date: Tue, 22 Oct 2013 15:41:04 +0530	[thread overview]
Message-ID: <1382436668-15813-4-git-send-email-rahul.sharma@samsung.com> (raw)
In-Reply-To: <1382436668-15813-1-git-send-email-rahul.sharma@samsung.com>

Exynos5420 hdmiphy device is a platform device, unlike
predecessor SoCs where it used to be a I2C device. This
support is added to the hdmiphy platform driver.

Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
---
 drivers/gpu/drm/exynos/Makefile                  |    1 +
 drivers/gpu/drm/exynos/exynos_hdmi.c             |   61 +++-
 drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c |  363 ++++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h     |    1 +
 4 files changed, 413 insertions(+), 13 deletions(-)
 create mode 100644 drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c

diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 463239b..eedd145 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -13,6 +13,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD)	+= exynos_drm_fimd.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o exynos_mixer.o \
 					   exynos_ddc.o exynos_hdmiphy_i2c.o \
+					   exynos_hdmiphy_platform.o \
 					   exynos_drm_hdmi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)	+= exynos_drm_vidi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_G2D)	+= exynos_drm_g2d.o
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 444541d..e199d7d 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -35,6 +35,7 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_i2c.h>
+#include <linux/of_platform.h>
 
 #include <drm/exynos_drm.h>
 
@@ -1608,10 +1609,14 @@ static int hdmi_register_phy_device(struct hdmi_context *hdata, bool i2c_dev)
 {
 	struct device_node *np;
 	struct i2c_client *client;
+	struct platform_device *pdev;
 	int ret;
 
 	/* register hdmiphy driver */
-	ret = exynos_hdmiphy_i2c_driver_register();
+	if (i2c_dev)
+		ret = exynos_hdmiphy_i2c_driver_register();
+	else
+		ret = exynos_hdmiphy_platform_driver_register();
 	if (ret) {
 		DRM_ERROR("failed to register phy driver. ret %d.\n", ret);
 		goto err;
@@ -1624,16 +1629,29 @@ static int hdmi_register_phy_device(struct hdmi_context *hdata, bool i2c_dev)
 		goto err;
 	}
 
-	/* find hdmi phy on i2c bus */
-	client = of_find_i2c_device_by_node(np);
-	if (!client) {
-		DRM_ERROR("Could not find i2c 'phy' device\n");
-		ret = -ENODEV;
-		goto err;
+	if (i2c_dev) {
+		/* find hdmi phy on i2c bus */
+		client = of_find_i2c_device_by_node(np);
+		if (!client) {
+			DRM_ERROR("Could not find i2c 'phy' device\n");
+			ret = -ENODEV;
+			goto err;
+		}
+		hdata->phy_dev = &client->dev;
+		hdata->phy_ops = exynos_hdmiphy_i2c_device_get_ops(
+					hdata->phy_dev);
+	} else {
+		/* find hdmi phy on platform bus */
+		pdev = of_find_device_by_node(np);
+		if (!pdev) {
+			DRM_ERROR("Could not find platform 'phy' device\n");
+			ret = -ENODEV;
+			goto err;
+		}
+		hdata->phy_dev = &pdev->dev;
+		hdata->phy_ops = exynos_hdmiphy_platform_device_get_ops(
+					hdata->phy_dev);
 	}
-	hdata->phy_dev = &client->dev;
-	hdata->phy_ops = exynos_hdmiphy_i2c_device_get_ops(
-				hdata->phy_dev);
 
 	if (!hdata->phy_ops) {
 		ret = -EINVAL;
@@ -1652,6 +1670,11 @@ static struct hdmi_drv_data exynos5250_hdmi_drv_data = {
 	.i2c_hdmiphy = 1,
 };
 
+static struct hdmi_drv_data exynos5420_hdmi_drv_data = {
+	.type = HDMI_TYPE14,
+	.i2c_hdmiphy = 0,
+};
+
 static struct of_device_id hdmi_match_types[] = {
 	{
 		.compatible = "samsung,exynos5-hdmi",
@@ -1660,6 +1683,9 @@ static struct of_device_id hdmi_match_types[] = {
 		.compatible = "samsung,exynos4212-hdmi",
 		.data	= &exynos5250_hdmi_drv_data,
 	}, {
+		.compatible = "samsung,exynos5420-hdmi",
+		.data	= &exynos5420_hdmi_drv_data,
+	}, {
 		/* end node */
 	}
 };
@@ -1767,7 +1793,10 @@ static int hdmi_probe(struct platform_device *pdev)
 	return 0;
 
 err_hdmiphy:
-	exynos_hdmiphy_i2c_driver_unregister();
+	if (drv->i2c_hdmiphy)
+		exynos_hdmiphy_i2c_driver_unregister();
+	else
+		exynos_hdmiphy_platform_driver_unregister();
 err_ddc:
 	i2c_del_driver(&ddc_driver);
 	return ret;
@@ -1776,11 +1805,17 @@ err_ddc:
 static int hdmi_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
+	struct hdmi_context *hdata = ctx->ctx;
 
 	pm_runtime_disable(dev);
 
-	/* hdmiphy i2c driver */
-	exynos_hdmiphy_i2c_driver_unregister();
+	/* hdmiphy driver */
+	if (i2c_verify_client(hdata->phy_dev))
+		exynos_hdmiphy_i2c_driver_unregister();
+	else
+		exynos_hdmiphy_platform_driver_unregister();
+
 	/* DDC i2c driver */
 	i2c_del_driver(&ddc_driver);
 
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c b/drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c
new file mode 100644
index 0000000..053d854
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_hdmiphy_platform.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co.Ltd
+ * Authors:
+ *	Rahul Sharma <rahul.sharma@samsung.com>
+ *
+ * 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.
+ *
+ */
+#include <drm/drmP.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "regs-hdmiphy.h"
+#include "exynos_hdmiphy.h"
+#include "exynos_hdmiphy_priv.h"
+
+/* default phy config settings for exynos5420 */
+static struct hdmiphy_config hdmiphy_5420_configs[] = {
+	{
+		.pixel_clock = 25200000,
+		.conf = {
+			0x52, 0x3F, 0x55, 0x40, 0x01, 0x00, 0xC8, 0x82,
+			0xC8, 0xBD, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x06,
+			0x80, 0x01, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xF4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 27000000,
+		.conf = {
+			0xD1, 0x22, 0x51, 0x40, 0x08, 0xFC, 0xE0, 0x98,
+			0xE8, 0xCB, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x06,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xE4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 27027000,
+		.conf = {
+			0xD1, 0x2D, 0x72, 0x40, 0x64, 0x12, 0xC8, 0x43,
+			0xE8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x06,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xE3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 36000000,
+		.conf = {
+			0x51, 0x2D, 0x55, 0x40, 0x40, 0x00, 0xC8, 0x02,
+			0xC8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xAB, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 40000000,
+		.conf = {
+			0xD1, 0x21, 0x31, 0x40, 0x3C, 0x28, 0xC8, 0x87,
+			0xE8, 0xC8, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x9A, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 65000000,
+		.conf = {
+			0xD1, 0x36, 0x34, 0x40, 0x0C, 0x04, 0xC8, 0x82,
+			0xE8, 0x45, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xBD, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 71000000,
+		.conf = {
+			0xD1, 0x3B, 0x35, 0x40, 0x0C, 0x04, 0xC8, 0x85,
+			0xE8, 0x63, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x57, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 74176000,
+		.conf = {
+			0xD1, 0x1F, 0x10, 0x40, 0x5B, 0xEF, 0xC8, 0x81,
+			0xE8, 0xB9, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x56,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xA6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 74250000,
+		.conf = {
+			0xD1, 0x1F, 0x10, 0x40, 0x40, 0xF8, 0xC8, 0x81,
+			0xE8, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x56,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xA5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 83500000,
+		.conf = {
+			0xD1, 0x23, 0x11, 0x40, 0x0C, 0xFB, 0xC8, 0x85,
+			0xE8, 0xD1, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x4A, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 106500000,
+		.conf = {
+			0xD1, 0x2C, 0x12, 0x40, 0x0C, 0x09, 0xC8, 0x84,
+			0xE8, 0x0A, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 108000000,
+		.conf = {
+			0x51, 0x2D, 0x15, 0x40, 0x01, 0x00, 0xC8, 0x82,
+			0xC8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0xC7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 146250000,
+		.conf = {
+			0xD1, 0x3D, 0x15, 0x40, 0x18, 0xFD, 0xC8, 0x83,
+			0xE8, 0x6E, 0xD9, 0x45, 0xA0, 0xAC, 0x80, 0x08,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x54, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+	{
+		.pixel_clock = 148500000,
+		.conf = {
+			0xD1, 0x1F, 0x00, 0x40, 0x40, 0xF8, 0xC8, 0x81,
+			0xE8, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80, 0x66,
+			0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66, 0x54,
+			0x4B, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+		},
+	},
+};
+
+static struct hdmiphy_config *hdmiphy_find_conf(struct hdmiphy_context *hdata,
+			unsigned int pixel_clk)
+{
+	int i;
+
+	for (i = 0; i < hdata->nr_confs; i++)
+		if (hdata->confs[i].pixel_clock == pixel_clk)
+			return &hdata->confs[i];
+
+	return NULL;
+}
+
+static int hdmiphy_reg_writeb(struct hdmiphy_context *hdata,
+			u32 reg_offset, u8 value)
+{
+	if (reg_offset >= HDMIPHY_REG_COUNT)
+		return -EINVAL;
+
+	writeb(value, hdata->regs + (reg_offset<<2));
+	return 0;
+}
+
+static int hdmiphy_reg_write_buf(struct hdmiphy_context *hdata,
+			u32 reg_offset, const u8 *buf, u32 len)
+{
+	int i;
+
+	if ((reg_offset + len) > HDMIPHY_REG_COUNT)
+		return -EINVAL;
+
+	for (i = 0; i < len; i++)
+		writeb(buf[i], hdata->regs +
+			((reg_offset + i)<<2));
+	return 0;
+}
+
+static int hdmiphy_check_mode(struct device *dev,
+			struct drm_display_mode *mode)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+	const struct hdmiphy_config *conf;
+
+	DRM_DEBUG("%s xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
+		__func__, mode->hdisplay, mode->vdisplay,
+		mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		? true : false, mode->clock * 1000);
+
+	conf = hdmiphy_find_conf(hdata, mode->clock * 1000);
+	if (!conf) {
+		DRM_DEBUG("Display Mode is not supported.\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int hdmiphy_mode_set(struct device *dev,
+			struct drm_display_mode *mode)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	hdata->current_conf = hdmiphy_find_conf(hdata, mode->clock * 1000);
+	if (!hdata->current_conf) {
+		DRM_ERROR("Display Mode is not supported.\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int hdmiphy_commit(struct device *dev)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+	int ret;
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	ret = hdmiphy_reg_write_buf(hdata, 1, hdata->current_conf->conf,
+			HDMIPHY_REG_COUNT - 1);
+	if (ret) {
+		DRM_ERROR("failed to configure hdmiphy. ret %d.\n", ret);
+		return ret;
+	}
+
+	/* need this delay before phy can be set to operation. */
+	usleep_range(10000, 12000);
+	return 0;
+}
+
+static void hdmiphy_enable(struct device *dev, int enable)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	if (enable)
+		hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
+				HDMIPHY_MODE_EN);
+	else
+		hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE, 0);
+}
+
+static void hdmiphy_poweron(struct device *dev, int mode)
+{
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+}
+
+struct exynos_hdmiphy_ops *exynos_hdmiphy_platform_device_get_ops
+			(struct device *dev)
+{
+	struct hdmiphy_context *hdata = dev_get_drvdata(dev);
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	if (hdata)
+		return hdata->ops;
+
+	return NULL;
+}
+
+static struct exynos_hdmiphy_ops phy_ops = {
+	.check_mode = hdmiphy_check_mode,
+	.mode_set = hdmiphy_mode_set,
+	.commit = hdmiphy_commit,
+	.enable = hdmiphy_enable,
+	.poweron = hdmiphy_poweron,
+};
+
+static struct hdmiphy_drv_data exynos5420_hdmiphy_drv_data = {
+	.confs = hdmiphy_5420_configs,
+	.count = ARRAY_SIZE(hdmiphy_5420_configs)
+};
+
+static struct of_device_id hdmiphy_platform_device_match_types[] = {
+	{
+		.compatible = "samsung,exynos5420-hdmiphy",
+		.data	= &exynos5420_hdmiphy_drv_data,
+	}, {
+		/* end node */
+	}
+};
+
+static int hdmiphy_platform_device_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct hdmiphy_context *hdata;
+	struct hdmiphy_drv_data *drv;
+	struct resource *res;
+	const struct of_device_id *match;
+
+	DRM_DEBUG_KMS("[%d]\n", __LINE__);
+
+	hdata = devm_kzalloc(dev, sizeof(*hdata), GFP_KERNEL);
+	if (!hdata) {
+		DRM_ERROR("failed to allocate hdmiphy context.\n");
+		return -ENOMEM;
+	}
+
+	match = of_match_node(of_match_ptr(
+		hdmiphy_platform_device_match_types),
+		dev->of_node);
+
+	if (!match)
+		return -ENODEV;
+
+	drv = (struct hdmiphy_drv_data *)match->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		DRM_ERROR("failed to find phy registers\n");
+		return -ENOENT;
+	}
+
+	hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
+	if (!hdata->regs) {
+		DRM_ERROR("failed to map registers\n");
+		return -ENXIO;
+	}
+
+	hdata->confs = drv->confs;
+	hdata->nr_confs = drv->count;
+	hdata->ops = &phy_ops;
+
+	platform_set_drvdata(pdev, hdata);
+	return 0;
+}
+
+struct platform_driver hdmiphy_platform_driver = {
+	.driver = {
+		.name	= "exynos-hdmiphy",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(
+				hdmiphy_platform_device_match_types),
+	},
+	.probe		= hdmiphy_platform_device_probe,
+};
+
+int exynos_hdmiphy_platform_driver_register(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&hdmiphy_platform_driver);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+void exynos_hdmiphy_platform_driver_unregister(void)
+{
+	platform_driver_unregister(&hdmiphy_platform_driver);
+}
diff --git a/drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h b/drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h
index 4948c81..9ba46d4 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h
+++ b/drivers/gpu/drm/exynos/exynos_hdmiphy_priv.h
@@ -15,6 +15,7 @@
 
 struct hdmiphy_context {
 	/* hdmiphy resources */
+	void __iomem		*regs;
 	struct exynos_hdmiphy_ops	*ops;
 	struct hdmiphy_config	*confs;
 	unsigned int		nr_confs;
-- 
1.7.10.4

  parent reply	other threads:[~2013-10-22 10:11 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-22 10:11 [PATCH v2 0/7] drm/exynos: move hdmiphy related code to hdmiphy driver Rahul Sharma
2013-10-22 10:11 ` Rahul Sharma
2013-10-22 10:11 ` [PATCH v2 1/7] drm/exynos: move hdmiphy code to hdmiphy i2c driver Rahul Sharma
2013-10-22 10:11   ` Rahul Sharma
2013-10-22 10:11 ` [PATCH v2 2/7] drm/exynos: remove dummy hdmiphy clock Rahul Sharma
2013-10-22 10:11   ` Rahul Sharma
2013-10-22 10:11 ` Rahul Sharma [this message]
2013-10-22 10:11   ` [PATCH v2 3/7] drm/exynos: add hdmiphy platform driver for exynos5420 Rahul Sharma
2013-10-22 10:11 ` [PATCH v2 4/7] drm/exynos: add hdmiphy pmu bit control in hdmiphy drivers Rahul Sharma
2013-10-22 10:11   ` Rahul Sharma
2013-10-22 10:11 ` [PATCH v2 5/7] exynos/drm: fix ddc i2c device probe failure Rahul Sharma
2013-10-22 10:11   ` Rahul Sharma
2013-10-22 10:11 ` [PATCH v2 6/7] ARM: dts: update hdmiphy dt node for exynos5250 Rahul Sharma
2013-10-22 10:11   ` Rahul Sharma
     [not found] ` <1382436668-15813-1-git-send-email-rahul.sharma-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-22 10:11   ` [PATCH v2 7/7] ARM: dts: update hdmiphy dt node for exynos5420 Rahul Sharma
2013-10-22 10:11     ` Rahul Sharma
2013-10-28 13:40 ` [PATCH v2 0/7] drm/exynos: move hdmiphy related code to hdmiphy driver Inki Dae
2013-10-28 13:40   ` Inki Dae
2013-10-29  3:36   ` Rahul Sharma
2013-10-29  3:36     ` Rahul Sharma

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1382436668-15813-4-git-send-email-rahul.sharma@samsung.com \
    --to=rahul.sharma@samsung.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=inki.dae@samsung.com \
    --cc=joshi@samsung.com \
    --cc=kgene.kim@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=r.sh.open@gmail.com \
    --cc=s.nawrocki@samsung.com \
    --cc=seanpaul@chromium.org \
    --cc=sw0312.kim@samsung.com \
    --cc=tomasz.figa@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.