diff mbox series

[1/4] drm/panel: s6e63m0: Break out SPI transport

Message ID 20200809215104.1830206-2-linus.walleij@linaro.org
State Accepted
Commit b7b23e4476872d80b7d70cd24e158a0505fdad5f
Headers show
Series drm/panel: s6e63m0: Add DSI transport | expand

Commit Message

Linus Walleij Aug. 9, 2020, 9:51 p.m. UTC
This panel can be accessed using both SPI and DSI.

To make it possible to probe and use the device also from
a DSI bus, first break out the SPI support to its own file.

Since all the panel driver does is write DCS commands to
the panel, we pass a DCS write function to probe()
from each subdriver.

We make the Kconfig entry for SPI mode default so all
current users will continue to work.

Cc: Stephan Gerhold <stephan@gerhold.net>
Cc: Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/gpu/drm/panel/Kconfig                 | 15 +++-
 drivers/gpu/drm/panel/Makefile                |  1 +
 .../gpu/drm/panel/panel-samsung-s6e63m0-spi.c | 89 +++++++++++++++++++
 drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 80 +++--------------
 drivers/gpu/drm/panel/panel-samsung-s6e63m0.h | 10 +++
 5 files changed, 124 insertions(+), 71 deletions(-)
 create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
 create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e63m0.h
diff mbox series

Patch

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 39055c1f0e2f..96e1548e475f 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -326,13 +326,22 @@  config DRM_PANEL_SAMSUNG_S6E63J0X03
 	select VIDEOMODE_HELPERS
 
 config DRM_PANEL_SAMSUNG_S6E63M0
-	tristate "Samsung S6E63M0 RGB/SPI panel"
+	tristate "Samsung S6E63M0 RGB panel"
 	depends on OF
-	depends on SPI
 	depends on BACKLIGHT_CLASS_DEVICE
 	help
 	  Say Y here if you want to enable support for Samsung S6E63M0
-	  AMOLED LCD panel.
+	  AMOLED LCD panel. This panel can be accessed using SPI or
+	  DSI.
+
+config DRM_PANEL_SAMSUNG_S6E63M0_SPI
+	tristate "Samsung S6E63M0 RGB SPI interface"
+	depends on SPI
+	depends on DRM_PANEL_SAMSUNG_S6E63M0
+	default DRM_PANEL_SAMSUNG_S6E63M0
+	help
+	  Say Y here if you want to be able to access the Samsung
+	  S6E63M0 panel using SPI.
 
 config DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01
 	tristate "Samsung AMS452EF01 panel with S6E88A0 DSI video mode controller"
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index de74f282c433..9cf71adfa794 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -34,6 +34,7 @@  obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_SPI) += panel-samsung-s6e63m0-spi.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01) += panel-samsung-s6e88a0-ams452ef01.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o
 obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
new file mode 100644
index 000000000000..4082fbd75b79
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
@@ -0,0 +1,89 @@ 
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+
+#include <drm/drm_print.h>
+
+#include "panel-samsung-s6e63m0.h"
+
+#define DATA_MASK	0x100
+
+static int s6e63m0_spi_write_word(struct device *dev, u16 data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct spi_transfer xfer = {
+		.len	= 2,
+		.tx_buf = &data,
+	};
+	struct spi_message msg;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	return spi_sync(spi, &msg);
+}
+
+static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len)
+{
+	int ret = 0;
+
+	DRM_DEV_DEBUG(dev, "SPI writing dcs seq: %*ph\n", (int)len, data);
+	ret = s6e63m0_spi_write_word(dev, *data);
+
+	while (!ret && --len) {
+		++data;
+		ret = s6e63m0_spi_write_word(dev, *data | DATA_MASK);
+	}
+
+	if (ret) {
+		DRM_DEV_ERROR(dev, "SPI error %d writing dcs seq: %*ph\n", ret,
+			      (int)len, data);
+	}
+
+	usleep_range(300, 310);
+
+	return ret;
+}
+
+static int s6e63m0_spi_probe(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	int ret;
+
+	spi->bits_per_word = 9;
+	spi->mode = SPI_MODE_3;
+	ret = spi_setup(spi);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "spi setup failed.\n");
+		return ret;
+	}
+	return s6e63m0_probe(dev, s6e63m0_spi_dcs_write);
+}
+
+static int s6e63m0_spi_remove(struct spi_device *spi)
+{
+	return s6e63m0_remove(&spi->dev);
+}
+
+static const struct of_device_id s6e63m0_spi_of_match[] = {
+	{ .compatible = "samsung,s6e63m0" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s6e63m0_spi_of_match);
+
+static struct spi_driver s6e63m0_spi_driver = {
+	.probe			= s6e63m0_spi_probe,
+	.remove			= s6e63m0_spi_remove,
+	.driver			= {
+		.name		= "panel-samsung-s6e63m0",
+		.of_match_table = s6e63m0_spi_of_match,
+	},
+};
+module_spi_driver(s6e63m0_spi_driver);
+
+MODULE_AUTHOR("Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>");
+MODULE_DESCRIPTION("s6e63m0 LCD SPI Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
index a5f76eb4fa25..610676ef8a75 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
@@ -17,10 +17,11 @@ 
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/regulator/consumer.h>
-#include <linux/spi/spi.h>
 
 #include <video/mipi_display.h>
 
+#include "panel-samsung-s6e63m0.h"
+
 /* Manufacturer Command Set */
 #define MCS_ELVSS_ON                0xb1
 #define MCS_MIECTL1                0xc0
@@ -34,8 +35,6 @@ 
 #define NUM_GAMMA_LEVELS             11
 #define GAMMA_TABLE_COUNT           23
 
-#define DATA_MASK                                       0x100
-
 #define MAX_BRIGHTNESS              (NUM_GAMMA_LEVELS - 1)
 
 /* array of gamma tables for gamma value 2.2 */
@@ -88,6 +87,7 @@  static u8 const s6e63m0_gamma_22[NUM_GAMMA_LEVELS][GAMMA_TABLE_COUNT] = {
 
 struct s6e63m0 {
 	struct device *dev;
+	int (*dcs_write)(struct device *dev, const u8 *data, size_t len);
 	struct drm_panel panel;
 	struct backlight_device *bl_dev;
 
@@ -136,43 +136,12 @@  static int s6e63m0_clear_error(struct s6e63m0 *ctx)
 	return ret;
 }
 
-static int s6e63m0_spi_write_word(struct s6e63m0 *ctx, u16 data)
-{
-	struct spi_device *spi = to_spi_device(ctx->dev);
-	struct spi_transfer xfer = {
-		.len	= 2,
-		.tx_buf = &data,
-	};
-	struct spi_message msg;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-
-	return spi_sync(spi, &msg);
-}
-
 static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
 {
-	int ret = 0;
-
 	if (ctx->error < 0 || len == 0)
 		return;
 
-	DRM_DEV_DEBUG(ctx->dev, "writing dcs seq: %*ph\n", (int)len, data);
-	ret = s6e63m0_spi_write_word(ctx, *data);
-
-	while (!ret && --len) {
-		++data;
-		ret = s6e63m0_spi_write_word(ctx, *data | DATA_MASK);
-	}
-
-	if (ret) {
-		DRM_DEV_ERROR(ctx->dev, "error %d writing dcs seq: %*ph\n", ret,
-			      (int)len, data);
-		ctx->error = ret;
-	}
-
-	usleep_range(300, 310);
+	ctx->error = ctx->dcs_write(ctx->dev, data, len);
 }
 
 #define s6e63m0_dcs_write_seq_static(ctx, seq ...) \
@@ -433,9 +402,9 @@  static int s6e63m0_backlight_register(struct s6e63m0 *ctx)
 	return ret;
 }
 
-static int s6e63m0_probe(struct spi_device *spi)
+int s6e63m0_probe(struct device *dev,
+		  int (*dcs_write)(struct device *dev, const u8 *data, size_t len))
 {
-	struct device *dev = &spi->dev;
 	struct s6e63m0 *ctx;
 	int ret;
 
@@ -443,7 +412,8 @@  static int s6e63m0_probe(struct spi_device *spi)
 	if (!ctx)
 		return -ENOMEM;
 
-	spi_set_drvdata(spi, ctx);
+	ctx->dcs_write = dcs_write;
+	dev_set_drvdata(dev, ctx);
 
 	ctx->dev = dev;
 	ctx->enabled = false;
@@ -465,14 +435,6 @@  static int s6e63m0_probe(struct spi_device *spi)
 		return PTR_ERR(ctx->reset_gpio);
 	}
 
-	spi->bits_per_word = 9;
-	spi->mode = SPI_MODE_3;
-	ret = spi_setup(spi);
-	if (ret < 0) {
-		DRM_DEV_ERROR(dev, "spi setup failed.\n");
-		return ret;
-	}
-
 	drm_panel_init(&ctx->panel, dev, &s6e63m0_drm_funcs,
 		       DRM_MODE_CONNECTOR_DPI);
 
@@ -482,32 +444,14 @@  static int s6e63m0_probe(struct spi_device *spi)
 
 	return drm_panel_add(&ctx->panel);
 }
+EXPORT_SYMBOL_GPL(s6e63m0_probe);
 
-static int s6e63m0_remove(struct spi_device *spi)
+int s6e63m0_remove(struct device *dev)
 {
-	struct s6e63m0 *ctx = spi_get_drvdata(spi);
+	struct s6e63m0 *ctx = dev_get_drvdata(dev);
 
 	drm_panel_remove(&ctx->panel);
 
 	return 0;
 }
-
-static const struct of_device_id s6e63m0_of_match[] = {
-	{ .compatible = "samsung,s6e63m0" },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, s6e63m0_of_match);
-
-static struct spi_driver s6e63m0_driver = {
-	.probe			= s6e63m0_probe,
-	.remove			= s6e63m0_remove,
-	.driver			= {
-		.name		= "panel-samsung-s6e63m0",
-		.of_match_table = s6e63m0_of_match,
-	},
-};
-module_spi_driver(s6e63m0_driver);
-
-MODULE_AUTHOR("Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>");
-MODULE_DESCRIPTION("s6e63m0 LCD Driver");
-MODULE_LICENSE("GPL v2");
+EXPORT_SYMBOL_GPL(s6e63m0_remove);
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h
new file mode 100644
index 000000000000..44e31f39f211
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h
@@ -0,0 +1,10 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _PANEL_SAMSUNG_S6E63M0_H
+#define _PANEL_SAMSUNG_S6E63M0_H
+
+int s6e63m0_probe(struct device *dev,
+		  int (*dcs_write)(struct device *dev, const u8 *data, size_t len));
+int s6e63m0_remove(struct device *dev);
+
+#endif /* _PANEL_SAMSUNG_S6E63M0_H */