drm/panel: s6e63m0: Switch to DBI abstraction for SPI
authorLinus Walleij <linus.walleij@linaro.org>
Mon, 14 Jun 2021 18:11:35 +0000 (20:11 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 14 Jun 2021 20:22:27 +0000 (22:22 +0200)
The SPI access to s6e63m0 is using the DBI protocol, so switch
to using the elaborate DBI protocol implementation in the DRM
DBI helper library.

Acked-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20210614181135.1124445-2-linus.walleij@linaro.org
drivers/gpu/drm/panel/Kconfig
drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c
drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
drivers/gpu/drm/panel/panel-samsung-s6e63m0.h

index 7c32b04..09acd18 100644 (file)
@@ -388,6 +388,7 @@ config DRM_PANEL_SAMSUNG_S6E63M0_SPI
        depends on SPI
        depends on DRM_PANEL_SAMSUNG_S6E63M0
        default DRM_PANEL_SAMSUNG_S6E63M0
+       select DRM_MIPI_DBI
        help
          Say Y here if you want to be able to access the Samsung
          S6E63M0 panel using SPI.
index 07a48f6..e0b1a7e 100644 (file)
@@ -16,7 +16,8 @@
 #define MCS_GLOBAL_PARAM       0xb0
 #define S6E63M0_DSI_MAX_CHUNK  15 /* CMD + 15 bytes max */
 
-static int s6e63m0_dsi_dcs_read(struct device *dev, const u8 cmd, u8 *data)
+static int s6e63m0_dsi_dcs_read(struct device *dev, void *trsp,
+                               const u8 cmd, u8 *data)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
        int ret;
@@ -32,7 +33,8 @@ static int s6e63m0_dsi_dcs_read(struct device *dev, const u8 cmd, u8 *data)
        return 0;
 }
 
-static int s6e63m0_dsi_dcs_write(struct device *dev, const u8 *data, size_t len)
+static int s6e63m0_dsi_dcs_write(struct device *dev, void *trsp,
+                                const u8 *data, size_t len)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
        const u8 *seqp = data;
@@ -99,8 +101,8 @@ static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi)
        dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
                MIPI_DSI_MODE_VIDEO_BURST;
 
-       ret = s6e63m0_probe(dev, s6e63m0_dsi_dcs_read, s6e63m0_dsi_dcs_write,
-                           true);
+       ret = s6e63m0_probe(dev, NULL, s6e63m0_dsi_dcs_read,
+                           s6e63m0_dsi_dcs_write, true);
        if (ret)
                return ret;
 
index 326deb3..3669cc3 100644 (file)
@@ -5,62 +5,38 @@
 #include <linux/spi/spi.h>
 #include <linux/delay.h>
 
+#include <drm/drm_mipi_dbi.h>
 #include <drm/drm_print.h>
 
 #include "panel-samsung-s6e63m0.h"
 
-#define DATA_MASK      0x100
+static const u8 s6e63m0_dbi_read_commands[] = {
+       MCS_READ_ID1,
+       MCS_READ_ID2,
+       MCS_READ_ID3,
+       0, /* sentinel */
+};
 
-static int s6e63m0_spi_dcs_read(struct device *dev, const u8 cmd, u8 *data)
+static int s6e63m0_spi_dcs_read(struct device *dev, void *trsp,
+                               const u8 cmd, u8 *data)
 {
-       struct spi_device *spi = to_spi_device(dev);
-       u16 buf[1];
-       u16 rbuf[1];
+       struct mipi_dbi *dbi = trsp;
        int ret;
 
-       /* SPI buffers are always in CPU order */
-       buf[0] = (u16)cmd;
-       ret = spi_write_then_read(spi, buf, 2, rbuf, 2);
-       dev_dbg(dev, "READ CMD: %04x RET: %04x\n", buf[0], rbuf[0]);
-       if (!ret)
-               /* These high 8 bits of the 9 contains the readout */
-               *data = (rbuf[0] & 0x1ff) >> 1;
+       ret = mipi_dbi_command_read(dbi, cmd, data);
+       if (ret)
+               dev_err(dev, "error on DBI read command %02x\n", cmd);
 
        return ret;
 }
 
-static int s6e63m0_spi_write_word(struct device *dev, u16 data)
-{
-       struct spi_device *spi = to_spi_device(dev);
-
-       /* SPI buffers are always in CPU order */
-       return spi_write(spi, &data, 2);
-}
-
-static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len)
+static int s6e63m0_spi_dcs_write(struct device *dev, void *trsp,
+                                const u8 *data, size_t len)
 {
-       int ret = 0;
-
-       dev_dbg(dev, "SPI writing dcs seq: %*ph\n", (int)len, data);
-
-       /*
-        * This sends 9 bits with the first bit (bit 8) set to 0
-        * This indicates that this is a command. Anything after the
-        * command is data.
-        */
-       ret = s6e63m0_spi_write_word(dev, *data);
-
-       while (!ret && --len) {
-               ++data;
-               /* This sends 9 bits with the first bit (bit 8) set to 1 */
-               ret = s6e63m0_spi_write_word(dev, *data | DATA_MASK);
-       }
-
-       if (ret) {
-               dev_err(dev, "SPI error %d writing dcs seq: %*ph\n", ret,
-                       (int)len, data);
-       }
+       struct mipi_dbi *dbi = trsp;
+       int ret;
 
+       ret = mipi_dbi_command_stackbuf(dbi, data[0], (data + 1), (len - 1));
        usleep_range(300, 310);
 
        return ret;
@@ -69,18 +45,21 @@ static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len)
 static int s6e63m0_spi_probe(struct spi_device *spi)
 {
        struct device *dev = &spi->dev;
+       struct mipi_dbi *dbi;
        int ret;
 
-       spi->bits_per_word = 9;
-       /* Preserve e.g. SPI_3WIRE setting */
-       spi->mode |= SPI_MODE_3;
-       ret = spi_setup(spi);
-       if (ret < 0) {
-               dev_err(dev, "spi setup failed.\n");
-               return ret;
-       }
-       return s6e63m0_probe(dev, s6e63m0_spi_dcs_read, s6e63m0_spi_dcs_write,
-                            false);
+       dbi = devm_kzalloc(dev, sizeof(*dbi), GFP_KERNEL);
+       if (!dbi)
+               return -ENOMEM;
+
+       ret = mipi_dbi_spi_init(spi, dbi, NULL);
+       if (ret)
+               return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
+       /* Register our custom MCS read commands */
+       dbi->read_commands = s6e63m0_dbi_read_commands;
+
+       return s6e63m0_probe(dev, dbi, s6e63m0_spi_dcs_read,
+                            s6e63m0_spi_dcs_write, false);
 }
 
 static int s6e63m0_spi_remove(struct spi_device *spi)
index 603c5df..35d72ac 100644 (file)
 
 #include "panel-samsung-s6e63m0.h"
 
-/* Manufacturer Command Set */
-#define MCS_ELVSS_ON           0xb1
-#define MCS_TEMP_SWIRE         0xb2
-#define MCS_PENTILE_1          0xb3
-#define MCS_PENTILE_2          0xb4
-#define MCS_GAMMA_DELTA_Y_RED  0xb5
-#define MCS_GAMMA_DELTA_X_RED  0xb6
-#define MCS_GAMMA_DELTA_Y_GREEN        0xb7
-#define MCS_GAMMA_DELTA_X_GREEN        0xb8
-#define MCS_GAMMA_DELTA_Y_BLUE 0xb9
-#define MCS_GAMMA_DELTA_X_BLUE 0xba
-#define MCS_MIECTL1            0xc0
-#define MCS_BCMODE             0xc1
-#define MCS_ERROR_CHECK                0xd5
-#define MCS_READ_ID1           0xda
-#define MCS_READ_ID2           0xdb
-#define MCS_READ_ID3           0xdc
-#define MCS_LEVEL_2_KEY                0xf0
-#define MCS_MTP_KEY            0xf1
-#define MCS_DISCTL             0xf2
-#define MCS_SRCCTL             0xf6
-#define MCS_IFCTL              0xf7
-#define MCS_PANELCTL           0xf8
-#define MCS_PGAMMACTL          0xfa
-
 #define S6E63M0_LCD_ID_VALUE_M2                0xA4
 #define S6E63M0_LCD_ID_VALUE_SM2       0xB4
 #define S6E63M0_LCD_ID_VALUE_SM2_1     0xB6
@@ -283,8 +258,9 @@ static u8 const s6e63m0_elvss_per_gamma[NUM_GAMMA_LEVELS] = {
 
 struct s6e63m0 {
        struct device *dev;
-       int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val);
-       int (*dcs_write)(struct device *dev, const u8 *data, size_t len);
+       void *transport_data;
+       int (*dcs_read)(struct device *dev, void *trsp, const u8 cmd, u8 *val);
+       int (*dcs_write)(struct device *dev, void *trsp, const u8 *data, size_t len);
        struct drm_panel panel;
        struct backlight_device *bl_dev;
        u8 lcd_type;
@@ -340,7 +316,7 @@ static void s6e63m0_dcs_read(struct s6e63m0 *ctx, const u8 cmd, u8 *data)
        if (ctx->error < 0)
                return;
 
-       ctx->error = ctx->dcs_read(ctx->dev, cmd, data);
+       ctx->error = ctx->dcs_read(ctx->dev, ctx->transport_data, cmd, data);
 }
 
 static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
@@ -348,7 +324,7 @@ static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
        if (ctx->error < 0 || len == 0)
                return;
 
-       ctx->error = ctx->dcs_write(ctx->dev, data, len);
+       ctx->error = ctx->dcs_write(ctx->dev, ctx->transport_data, data, len);
 }
 
 #define s6e63m0_dcs_write_seq_static(ctx, seq ...) \
@@ -713,9 +689,9 @@ static int s6e63m0_backlight_register(struct s6e63m0 *ctx, u32 max_brightness)
        return ret;
 }
 
-int s6e63m0_probe(struct device *dev,
-                 int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val),
-                 int (*dcs_write)(struct device *dev, const u8 *data, size_t len),
+int s6e63m0_probe(struct device *dev, void *trsp,
+                 int (*dcs_read)(struct device *dev, void *trsp, const u8 cmd, u8 *val),
+                 int (*dcs_write)(struct device *dev, void *trsp, const u8 *data, size_t len),
                  bool dsi_mode)
 {
        struct s6e63m0 *ctx;
@@ -726,6 +702,7 @@ int s6e63m0_probe(struct device *dev,
        if (!ctx)
                return -ENOMEM;
 
+       ctx->transport_data = trsp;
        ctx->dsi_mode = dsi_mode;
        ctx->dcs_read = dcs_read;
        ctx->dcs_write = dcs_write;
index c669fec..306605e 100644 (file)
@@ -3,9 +3,36 @@
 #ifndef _PANEL_SAMSUNG_S6E63M0_H
 #define _PANEL_SAMSUNG_S6E63M0_H
 
-int s6e63m0_probe(struct device *dev,
-                 int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val),
-                 int (*dcs_write)(struct device *dev, const u8 *data,
+/* Manufacturer Command Set */
+#define MCS_ELVSS_ON           0xb1
+#define MCS_TEMP_SWIRE         0xb2
+#define MCS_PENTILE_1          0xb3
+#define MCS_PENTILE_2          0xb4
+#define MCS_GAMMA_DELTA_Y_RED  0xb5
+#define MCS_GAMMA_DELTA_X_RED  0xb6
+#define MCS_GAMMA_DELTA_Y_GREEN        0xb7
+#define MCS_GAMMA_DELTA_X_GREEN        0xb8
+#define MCS_GAMMA_DELTA_Y_BLUE 0xb9
+#define MCS_GAMMA_DELTA_X_BLUE 0xba
+#define MCS_MIECTL1            0xc0
+#define MCS_BCMODE             0xc1
+#define MCS_ERROR_CHECK                0xd5
+#define MCS_READ_ID1           0xda
+#define MCS_READ_ID2           0xdb
+#define MCS_READ_ID3           0xdc
+#define MCS_LEVEL_2_KEY                0xf0
+#define MCS_MTP_KEY            0xf1
+#define MCS_DISCTL             0xf2
+#define MCS_SRCCTL             0xf6
+#define MCS_IFCTL              0xf7
+#define MCS_PANELCTL           0xf8
+#define MCS_PGAMMACTL          0xfa
+
+int s6e63m0_probe(struct device *dev, void *trsp,
+                 int (*dcs_read)(struct device *dev, void *trsp,
+                                 const u8 cmd, u8 *val),
+                 int (*dcs_write)(struct device *dev, void *trsp,
+                                  const u8 *data,
                                   size_t len),
                  bool dsi_mode);
 int s6e63m0_remove(struct device *dev);