From b7b23e4476872d80b7d70cd24e158a0505fdad5f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 9 Aug 2020 23:51:01 +0200 Subject: drm/panel: s6e63m0: Break out SPI transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. Signed-off-by: Linus Walleij Tested-by: Stephan Gerhold Cc: Paweł Chmiel Acked-by: Paul Cercueil Link: https://patchwork.freedesktop.org/patch/384873/ --- drivers/gpu/drm/panel/Kconfig | 15 +++- drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c | 89 +++++++++++++++++++++++ drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 79 +++----------------- drivers/gpu/drm/panel/panel-samsung-s6e63m0.h | 10 +++ 5 files changed, 124 insertions(+), 70 deletions(-) create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e63m0.h (limited to 'drivers/gpu/drm/panel') diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 8d97d07c5871..f8d61e6addc3 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -324,13 +324,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 15a4e7752951..63f53bd88649 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 +#include +#include +#include + +#include + +#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 "); +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 2cc772fdc456..64d95201a7d4 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -16,10 +16,11 @@ #include #include #include -#include #include