Skip to content

Commit

Permalink
drm/panel: s6e63m0: Switch to DBI abstraction for SPI
Browse files Browse the repository at this point in the history
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
  • Loading branch information
linusw committed Jun 14, 2021
1 parent 413f52f commit c2a6186
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 91 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/panel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 6 additions & 4 deletions drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down
83 changes: 31 additions & 52 deletions drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down
41 changes: 9 additions & 32 deletions drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,6 @@

#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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -340,15 +316,15 @@ 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)
{
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 ...) \
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
33 changes: 30 additions & 3 deletions drivers/gpu/drm/panel/panel-samsung-s6e63m0.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit c2a6186

Please sign in to comment.