Commit c2a61865 authored by Linus Walleij's avatar Linus Walleij

drm/panel: s6e63m0: Switch to DBI abstraction for SPI

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: default avatarNoralf Trønnes <noralf@tronnes.org>
Reviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20210614181135.1124445-2-linus.walleij@linaro.org
parent 413f52f1
...@@ -388,6 +388,7 @@ config DRM_PANEL_SAMSUNG_S6E63M0_SPI ...@@ -388,6 +388,7 @@ config DRM_PANEL_SAMSUNG_S6E63M0_SPI
depends on SPI depends on SPI
depends on DRM_PANEL_SAMSUNG_S6E63M0 depends on DRM_PANEL_SAMSUNG_S6E63M0
default DRM_PANEL_SAMSUNG_S6E63M0 default DRM_PANEL_SAMSUNG_S6E63M0
select DRM_MIPI_DBI
help help
Say Y here if you want to be able to access the Samsung Say Y here if you want to be able to access the Samsung
S6E63M0 panel using SPI. S6E63M0 panel using SPI.
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
#define MCS_GLOBAL_PARAM 0xb0 #define MCS_GLOBAL_PARAM 0xb0
#define S6E63M0_DSI_MAX_CHUNK 15 /* CMD + 15 bytes max */ #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); struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
int ret; int ret;
...@@ -32,7 +33,8 @@ static int s6e63m0_dsi_dcs_read(struct device *dev, const u8 cmd, u8 *data) ...@@ -32,7 +33,8 @@ static int s6e63m0_dsi_dcs_read(struct device *dev, const u8 cmd, u8 *data)
return 0; 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); struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
const u8 *seqp = data; const u8 *seqp = data;
...@@ -99,8 +101,8 @@ static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi) ...@@ -99,8 +101,8 @@ static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_BURST; MIPI_DSI_MODE_VIDEO_BURST;
ret = s6e63m0_probe(dev, s6e63m0_dsi_dcs_read, s6e63m0_dsi_dcs_write, ret = s6e63m0_probe(dev, NULL, s6e63m0_dsi_dcs_read,
true); s6e63m0_dsi_dcs_write, true);
if (ret) if (ret)
return ret; return ret;
......
...@@ -5,62 +5,38 @@ ...@@ -5,62 +5,38 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <drm/drm_mipi_dbi.h>
#include <drm/drm_print.h> #include <drm/drm_print.h>
#include "panel-samsung-s6e63m0.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); struct mipi_dbi *dbi = trsp;
u16 buf[1];
u16 rbuf[1];
int ret; int ret;
/* SPI buffers are always in CPU order */ ret = mipi_dbi_command_read(dbi, cmd, data);
buf[0] = (u16)cmd; if (ret)
ret = spi_write_then_read(spi, buf, 2, rbuf, 2); dev_err(dev, "error on DBI read command %02x\n", cmd);
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;
return ret; return ret;
} }
static int s6e63m0_spi_write_word(struct device *dev, u16 data) static int s6e63m0_spi_dcs_write(struct device *dev, void *trsp,
{ const u8 *data, size_t len)
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)
{ {
int ret = 0; struct mipi_dbi *dbi = trsp;
int ret;
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);
}
ret = mipi_dbi_command_stackbuf(dbi, data[0], (data + 1), (len - 1));
usleep_range(300, 310); usleep_range(300, 310);
return ret; return ret;
...@@ -69,18 +45,21 @@ static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len) ...@@ -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) static int s6e63m0_spi_probe(struct spi_device *spi)
{ {
struct device *dev = &spi->dev; struct device *dev = &spi->dev;
struct mipi_dbi *dbi;
int ret; int ret;
spi->bits_per_word = 9; dbi = devm_kzalloc(dev, sizeof(*dbi), GFP_KERNEL);
/* Preserve e.g. SPI_3WIRE setting */ if (!dbi)
spi->mode |= SPI_MODE_3; return -ENOMEM;
ret = spi_setup(spi);
if (ret < 0) { ret = mipi_dbi_spi_init(spi, dbi, NULL);
dev_err(dev, "spi setup failed.\n"); if (ret)
return ret; return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
} /* Register our custom MCS read commands */
return s6e63m0_probe(dev, s6e63m0_spi_dcs_read, s6e63m0_spi_dcs_write, dbi->read_commands = s6e63m0_dbi_read_commands;
false);
return s6e63m0_probe(dev, dbi, s6e63m0_spi_dcs_read,
s6e63m0_spi_dcs_write, false);
} }
static int s6e63m0_spi_remove(struct spi_device *spi) static int s6e63m0_spi_remove(struct spi_device *spi)
......
...@@ -22,31 +22,6 @@ ...@@ -22,31 +22,6 @@
#include "panel-samsung-s6e63m0.h" #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_M2 0xA4
#define S6E63M0_LCD_ID_VALUE_SM2 0xB4 #define S6E63M0_LCD_ID_VALUE_SM2 0xB4
#define S6E63M0_LCD_ID_VALUE_SM2_1 0xB6 #define S6E63M0_LCD_ID_VALUE_SM2_1 0xB6
...@@ -283,8 +258,9 @@ static u8 const s6e63m0_elvss_per_gamma[NUM_GAMMA_LEVELS] = { ...@@ -283,8 +258,9 @@ static u8 const s6e63m0_elvss_per_gamma[NUM_GAMMA_LEVELS] = {
struct s6e63m0 { struct s6e63m0 {
struct device *dev; struct device *dev;
int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val); void *transport_data;
int (*dcs_write)(struct device *dev, const u8 *data, size_t len); 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 drm_panel panel;
struct backlight_device *bl_dev; struct backlight_device *bl_dev;
u8 lcd_type; u8 lcd_type;
...@@ -340,7 +316,7 @@ static void s6e63m0_dcs_read(struct s6e63m0 *ctx, const u8 cmd, u8 *data) ...@@ -340,7 +316,7 @@ static void s6e63m0_dcs_read(struct s6e63m0 *ctx, const u8 cmd, u8 *data)
if (ctx->error < 0) if (ctx->error < 0)
return; 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) 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) ...@@ -348,7 +324,7 @@ static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
if (ctx->error < 0 || len == 0) if (ctx->error < 0 || len == 0)
return; 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 ...) \ #define s6e63m0_dcs_write_seq_static(ctx, seq ...) \
...@@ -713,9 +689,9 @@ static int s6e63m0_backlight_register(struct s6e63m0 *ctx, u32 max_brightness) ...@@ -713,9 +689,9 @@ static int s6e63m0_backlight_register(struct s6e63m0 *ctx, u32 max_brightness)
return ret; return ret;
} }
int s6e63m0_probe(struct device *dev, int s6e63m0_probe(struct device *dev, void *trsp,
int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val), int (*dcs_read)(struct device *dev, void *trsp, const u8 cmd, u8 *val),
int (*dcs_write)(struct device *dev, const u8 *data, size_t len), int (*dcs_write)(struct device *dev, void *trsp, const u8 *data, size_t len),
bool dsi_mode) bool dsi_mode)
{ {
struct s6e63m0 *ctx; struct s6e63m0 *ctx;
...@@ -726,6 +702,7 @@ int s6e63m0_probe(struct device *dev, ...@@ -726,6 +702,7 @@ int s6e63m0_probe(struct device *dev,
if (!ctx) if (!ctx)
return -ENOMEM; return -ENOMEM;
ctx->transport_data = trsp;
ctx->dsi_mode = dsi_mode; ctx->dsi_mode = dsi_mode;
ctx->dcs_read = dcs_read; ctx->dcs_read = dcs_read;
ctx->dcs_write = dcs_write; ctx->dcs_write = dcs_write;
......
...@@ -3,9 +3,36 @@ ...@@ -3,9 +3,36 @@
#ifndef _PANEL_SAMSUNG_S6E63M0_H #ifndef _PANEL_SAMSUNG_S6E63M0_H
#define _PANEL_SAMSUNG_S6E63M0_H #define _PANEL_SAMSUNG_S6E63M0_H
int s6e63m0_probe(struct device *dev, /* Manufacturer Command Set */
int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val), #define MCS_ELVSS_ON 0xb1
int (*dcs_write)(struct device *dev, const u8 *data, #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), size_t len),
bool dsi_mode); bool dsi_mode);
int s6e63m0_remove(struct device *dev); int s6e63m0_remove(struct device *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment