cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

panel-sitronix-st7789v.c (13445B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2017 Free Electrons
      4 */
      5
      6#include <linux/delay.h>
      7#include <linux/gpio/consumer.h>
      8#include <linux/module.h>
      9#include <linux/regulator/consumer.h>
     10#include <linux/spi/spi.h>
     11
     12#include <video/mipi_display.h>
     13
     14#include <drm/drm_device.h>
     15#include <drm/drm_modes.h>
     16#include <drm/drm_panel.h>
     17
     18#define ST7789V_COLMOD_RGB_FMT_18BITS		(6 << 4)
     19#define ST7789V_COLMOD_CTRL_FMT_18BITS		(6 << 0)
     20
     21#define ST7789V_RAMCTRL_CMD		0xb0
     22#define ST7789V_RAMCTRL_RM_RGB			BIT(4)
     23#define ST7789V_RAMCTRL_DM_RGB			BIT(0)
     24#define ST7789V_RAMCTRL_MAGIC			(3 << 6)
     25#define ST7789V_RAMCTRL_EPF(n)			(((n) & 3) << 4)
     26
     27#define ST7789V_RGBCTRL_CMD		0xb1
     28#define ST7789V_RGBCTRL_WO			BIT(7)
     29#define ST7789V_RGBCTRL_RCM(n)			(((n) & 3) << 5)
     30#define ST7789V_RGBCTRL_VSYNC_HIGH		BIT(3)
     31#define ST7789V_RGBCTRL_HSYNC_HIGH		BIT(2)
     32#define ST7789V_RGBCTRL_PCLK_HIGH		BIT(1)
     33#define ST7789V_RGBCTRL_VBP(n)			((n) & 0x7f)
     34#define ST7789V_RGBCTRL_HBP(n)			((n) & 0x1f)
     35
     36#define ST7789V_PORCTRL_CMD		0xb2
     37#define ST7789V_PORCTRL_IDLE_BP(n)		(((n) & 0xf) << 4)
     38#define ST7789V_PORCTRL_IDLE_FP(n)		((n) & 0xf)
     39#define ST7789V_PORCTRL_PARTIAL_BP(n)		(((n) & 0xf) << 4)
     40#define ST7789V_PORCTRL_PARTIAL_FP(n)		((n) & 0xf)
     41
     42#define ST7789V_GCTRL_CMD		0xb7
     43#define ST7789V_GCTRL_VGHS(n)			(((n) & 7) << 4)
     44#define ST7789V_GCTRL_VGLS(n)			((n) & 7)
     45
     46#define ST7789V_VCOMS_CMD		0xbb
     47
     48#define ST7789V_LCMCTRL_CMD		0xc0
     49#define ST7789V_LCMCTRL_XBGR			BIT(5)
     50#define ST7789V_LCMCTRL_XMX			BIT(3)
     51#define ST7789V_LCMCTRL_XMH			BIT(2)
     52
     53#define ST7789V_VDVVRHEN_CMD		0xc2
     54#define ST7789V_VDVVRHEN_CMDEN			BIT(0)
     55
     56#define ST7789V_VRHS_CMD		0xc3
     57
     58#define ST7789V_VDVS_CMD		0xc4
     59
     60#define ST7789V_FRCTRL2_CMD		0xc6
     61
     62#define ST7789V_PWCTRL1_CMD		0xd0
     63#define ST7789V_PWCTRL1_MAGIC			0xa4
     64#define ST7789V_PWCTRL1_AVDD(n)			(((n) & 3) << 6)
     65#define ST7789V_PWCTRL1_AVCL(n)			(((n) & 3) << 4)
     66#define ST7789V_PWCTRL1_VDS(n)			((n) & 3)
     67
     68#define ST7789V_PVGAMCTRL_CMD		0xe0
     69#define ST7789V_PVGAMCTRL_JP0(n)		(((n) & 3) << 4)
     70#define ST7789V_PVGAMCTRL_JP1(n)		(((n) & 3) << 4)
     71#define ST7789V_PVGAMCTRL_VP0(n)		((n) & 0xf)
     72#define ST7789V_PVGAMCTRL_VP1(n)		((n) & 0x3f)
     73#define ST7789V_PVGAMCTRL_VP2(n)		((n) & 0x3f)
     74#define ST7789V_PVGAMCTRL_VP4(n)		((n) & 0x1f)
     75#define ST7789V_PVGAMCTRL_VP6(n)		((n) & 0x1f)
     76#define ST7789V_PVGAMCTRL_VP13(n)		((n) & 0xf)
     77#define ST7789V_PVGAMCTRL_VP20(n)		((n) & 0x7f)
     78#define ST7789V_PVGAMCTRL_VP27(n)		((n) & 7)
     79#define ST7789V_PVGAMCTRL_VP36(n)		(((n) & 7) << 4)
     80#define ST7789V_PVGAMCTRL_VP43(n)		((n) & 0x7f)
     81#define ST7789V_PVGAMCTRL_VP50(n)		((n) & 0xf)
     82#define ST7789V_PVGAMCTRL_VP57(n)		((n) & 0x1f)
     83#define ST7789V_PVGAMCTRL_VP59(n)		((n) & 0x1f)
     84#define ST7789V_PVGAMCTRL_VP61(n)		((n) & 0x3f)
     85#define ST7789V_PVGAMCTRL_VP62(n)		((n) & 0x3f)
     86#define ST7789V_PVGAMCTRL_VP63(n)		(((n) & 0xf) << 4)
     87
     88#define ST7789V_NVGAMCTRL_CMD		0xe1
     89#define ST7789V_NVGAMCTRL_JN0(n)		(((n) & 3) << 4)
     90#define ST7789V_NVGAMCTRL_JN1(n)		(((n) & 3) << 4)
     91#define ST7789V_NVGAMCTRL_VN0(n)		((n) & 0xf)
     92#define ST7789V_NVGAMCTRL_VN1(n)		((n) & 0x3f)
     93#define ST7789V_NVGAMCTRL_VN2(n)		((n) & 0x3f)
     94#define ST7789V_NVGAMCTRL_VN4(n)		((n) & 0x1f)
     95#define ST7789V_NVGAMCTRL_VN6(n)		((n) & 0x1f)
     96#define ST7789V_NVGAMCTRL_VN13(n)		((n) & 0xf)
     97#define ST7789V_NVGAMCTRL_VN20(n)		((n) & 0x7f)
     98#define ST7789V_NVGAMCTRL_VN27(n)		((n) & 7)
     99#define ST7789V_NVGAMCTRL_VN36(n)		(((n) & 7) << 4)
    100#define ST7789V_NVGAMCTRL_VN43(n)		((n) & 0x7f)
    101#define ST7789V_NVGAMCTRL_VN50(n)		((n) & 0xf)
    102#define ST7789V_NVGAMCTRL_VN57(n)		((n) & 0x1f)
    103#define ST7789V_NVGAMCTRL_VN59(n)		((n) & 0x1f)
    104#define ST7789V_NVGAMCTRL_VN61(n)		((n) & 0x3f)
    105#define ST7789V_NVGAMCTRL_VN62(n)		((n) & 0x3f)
    106#define ST7789V_NVGAMCTRL_VN63(n)		(((n) & 0xf) << 4)
    107
    108#define ST7789V_TEST(val, func)			\
    109	do {					\
    110		if ((val = (func)))		\
    111			return val;		\
    112	} while (0)
    113
    114struct st7789v {
    115	struct drm_panel panel;
    116	struct spi_device *spi;
    117	struct gpio_desc *reset;
    118	struct regulator *power;
    119};
    120
    121enum st7789v_prefix {
    122	ST7789V_COMMAND = 0,
    123	ST7789V_DATA = 1,
    124};
    125
    126static inline struct st7789v *panel_to_st7789v(struct drm_panel *panel)
    127{
    128	return container_of(panel, struct st7789v, panel);
    129}
    130
    131static int st7789v_spi_write(struct st7789v *ctx, enum st7789v_prefix prefix,
    132			     u8 data)
    133{
    134	struct spi_transfer xfer = { };
    135	struct spi_message msg;
    136	u16 txbuf = ((prefix & 1) << 8) | data;
    137
    138	spi_message_init(&msg);
    139
    140	xfer.tx_buf = &txbuf;
    141	xfer.bits_per_word = 9;
    142	xfer.len = sizeof(txbuf);
    143
    144	spi_message_add_tail(&xfer, &msg);
    145	return spi_sync(ctx->spi, &msg);
    146}
    147
    148static int st7789v_write_command(struct st7789v *ctx, u8 cmd)
    149{
    150	return st7789v_spi_write(ctx, ST7789V_COMMAND, cmd);
    151}
    152
    153static int st7789v_write_data(struct st7789v *ctx, u8 cmd)
    154{
    155	return st7789v_spi_write(ctx, ST7789V_DATA, cmd);
    156}
    157
    158static const struct drm_display_mode default_mode = {
    159	.clock = 7000,
    160	.hdisplay = 240,
    161	.hsync_start = 240 + 38,
    162	.hsync_end = 240 + 38 + 10,
    163	.htotal = 240 + 38 + 10 + 10,
    164	.vdisplay = 320,
    165	.vsync_start = 320 + 8,
    166	.vsync_end = 320 + 8 + 4,
    167	.vtotal = 320 + 8 + 4 + 4,
    168};
    169
    170static int st7789v_get_modes(struct drm_panel *panel,
    171			     struct drm_connector *connector)
    172{
    173	struct drm_display_mode *mode;
    174
    175	mode = drm_mode_duplicate(connector->dev, &default_mode);
    176	if (!mode) {
    177		dev_err(panel->dev, "failed to add mode %ux%ux@%u\n",
    178			default_mode.hdisplay, default_mode.vdisplay,
    179			drm_mode_vrefresh(&default_mode));
    180		return -ENOMEM;
    181	}
    182
    183	drm_mode_set_name(mode);
    184
    185	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
    186	drm_mode_probed_add(connector, mode);
    187
    188	connector->display_info.width_mm = 61;
    189	connector->display_info.height_mm = 103;
    190
    191	return 1;
    192}
    193
    194static int st7789v_prepare(struct drm_panel *panel)
    195{
    196	struct st7789v *ctx = panel_to_st7789v(panel);
    197	int ret;
    198
    199	ret = regulator_enable(ctx->power);
    200	if (ret)
    201		return ret;
    202
    203	gpiod_set_value(ctx->reset, 1);
    204	msleep(30);
    205	gpiod_set_value(ctx->reset, 0);
    206	msleep(120);
    207
    208	ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_EXIT_SLEEP_MODE));
    209
    210	/* We need to wait 120ms after a sleep out command */
    211	msleep(120);
    212
    213	ST7789V_TEST(ret, st7789v_write_command(ctx,
    214						MIPI_DCS_SET_ADDRESS_MODE));
    215	ST7789V_TEST(ret, st7789v_write_data(ctx, 0));
    216
    217	ST7789V_TEST(ret, st7789v_write_command(ctx,
    218						MIPI_DCS_SET_PIXEL_FORMAT));
    219	ST7789V_TEST(ret, st7789v_write_data(ctx,
    220					     (MIPI_DCS_PIXEL_FMT_18BIT << 4) |
    221					     (MIPI_DCS_PIXEL_FMT_18BIT)));
    222
    223	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PORCTRL_CMD));
    224	ST7789V_TEST(ret, st7789v_write_data(ctx, 0xc));
    225	ST7789V_TEST(ret, st7789v_write_data(ctx, 0xc));
    226	ST7789V_TEST(ret, st7789v_write_data(ctx, 0));
    227	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PORCTRL_IDLE_BP(3) |
    228					     ST7789V_PORCTRL_IDLE_FP(3)));
    229	ST7789V_TEST(ret, st7789v_write_data(ctx,
    230					     ST7789V_PORCTRL_PARTIAL_BP(3) |
    231					     ST7789V_PORCTRL_PARTIAL_FP(3)));
    232
    233	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_GCTRL_CMD));
    234	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_GCTRL_VGLS(5) |
    235					     ST7789V_GCTRL_VGHS(3)));
    236
    237	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VCOMS_CMD));
    238	ST7789V_TEST(ret, st7789v_write_data(ctx, 0x2b));
    239
    240	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_LCMCTRL_CMD));
    241	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_LCMCTRL_XMH |
    242					     ST7789V_LCMCTRL_XMX |
    243					     ST7789V_LCMCTRL_XBGR));
    244
    245	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VDVVRHEN_CMD));
    246	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_VDVVRHEN_CMDEN));
    247
    248	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VRHS_CMD));
    249	ST7789V_TEST(ret, st7789v_write_data(ctx, 0xf));
    250
    251	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VDVS_CMD));
    252	ST7789V_TEST(ret, st7789v_write_data(ctx, 0x20));
    253
    254	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_FRCTRL2_CMD));
    255	ST7789V_TEST(ret, st7789v_write_data(ctx, 0xf));
    256
    257	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PWCTRL1_CMD));
    258	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PWCTRL1_MAGIC));
    259	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PWCTRL1_AVDD(2) |
    260					     ST7789V_PWCTRL1_AVCL(2) |
    261					     ST7789V_PWCTRL1_VDS(1)));
    262
    263	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PVGAMCTRL_CMD));
    264	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP63(0xd)));
    265	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP1(0xca)));
    266	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP2(0xe)));
    267	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP4(8)));
    268	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP6(9)));
    269	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP13(7)));
    270	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP20(0x2d)));
    271	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP27(0xb) |
    272					     ST7789V_PVGAMCTRL_VP36(3)));
    273	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP43(0x3d)));
    274	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_JP1(3) |
    275					     ST7789V_PVGAMCTRL_VP50(4)));
    276	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP57(0xa)));
    277	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP59(0xa)));
    278	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP61(0x1b)));
    279	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP62(0x28)));
    280
    281	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_NVGAMCTRL_CMD));
    282	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN63(0xd)));
    283	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN1(0xca)));
    284	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN2(0xf)));
    285	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN4(8)));
    286	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN6(8)));
    287	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN13(7)));
    288	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN20(0x2e)));
    289	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN27(0xc) |
    290					     ST7789V_NVGAMCTRL_VN36(5)));
    291	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN43(0x40)));
    292	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_JN1(3) |
    293					     ST7789V_NVGAMCTRL_VN50(4)));
    294	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN57(9)));
    295	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN59(0xb)));
    296	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN61(0x1b)));
    297	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN62(0x28)));
    298
    299	ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_ENTER_INVERT_MODE));
    300
    301	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_RAMCTRL_CMD));
    302	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RAMCTRL_DM_RGB |
    303					     ST7789V_RAMCTRL_RM_RGB));
    304	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RAMCTRL_EPF(3) |
    305					     ST7789V_RAMCTRL_MAGIC));
    306
    307	ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_RGBCTRL_CMD));
    308	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_WO |
    309					     ST7789V_RGBCTRL_RCM(2) |
    310					     ST7789V_RGBCTRL_VSYNC_HIGH |
    311					     ST7789V_RGBCTRL_HSYNC_HIGH |
    312					     ST7789V_RGBCTRL_PCLK_HIGH));
    313	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_VBP(8)));
    314	ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_HBP(20)));
    315
    316	return 0;
    317}
    318
    319static int st7789v_enable(struct drm_panel *panel)
    320{
    321	struct st7789v *ctx = panel_to_st7789v(panel);
    322
    323	return st7789v_write_command(ctx, MIPI_DCS_SET_DISPLAY_ON);
    324}
    325
    326static int st7789v_disable(struct drm_panel *panel)
    327{
    328	struct st7789v *ctx = panel_to_st7789v(panel);
    329	int ret;
    330
    331	ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_SET_DISPLAY_OFF));
    332
    333	return 0;
    334}
    335
    336static int st7789v_unprepare(struct drm_panel *panel)
    337{
    338	struct st7789v *ctx = panel_to_st7789v(panel);
    339	int ret;
    340
    341	ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_ENTER_SLEEP_MODE));
    342
    343	regulator_disable(ctx->power);
    344
    345	return 0;
    346}
    347
    348static const struct drm_panel_funcs st7789v_drm_funcs = {
    349	.disable	= st7789v_disable,
    350	.enable		= st7789v_enable,
    351	.get_modes	= st7789v_get_modes,
    352	.prepare	= st7789v_prepare,
    353	.unprepare	= st7789v_unprepare,
    354};
    355
    356static int st7789v_probe(struct spi_device *spi)
    357{
    358	struct st7789v *ctx;
    359	int ret;
    360
    361	ctx = devm_kzalloc(&spi->dev, sizeof(*ctx), GFP_KERNEL);
    362	if (!ctx)
    363		return -ENOMEM;
    364
    365	spi_set_drvdata(spi, ctx);
    366	ctx->spi = spi;
    367
    368	drm_panel_init(&ctx->panel, &spi->dev, &st7789v_drm_funcs,
    369		       DRM_MODE_CONNECTOR_DPI);
    370
    371	ctx->power = devm_regulator_get(&spi->dev, "power");
    372	if (IS_ERR(ctx->power))
    373		return PTR_ERR(ctx->power);
    374
    375	ctx->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);
    376	if (IS_ERR(ctx->reset)) {
    377		dev_err(&spi->dev, "Couldn't get our reset line\n");
    378		return PTR_ERR(ctx->reset);
    379	}
    380
    381	ret = drm_panel_of_backlight(&ctx->panel);
    382	if (ret)
    383		return ret;
    384
    385	drm_panel_add(&ctx->panel);
    386
    387	return 0;
    388}
    389
    390static void st7789v_remove(struct spi_device *spi)
    391{
    392	struct st7789v *ctx = spi_get_drvdata(spi);
    393
    394	drm_panel_remove(&ctx->panel);
    395}
    396
    397static const struct of_device_id st7789v_of_match[] = {
    398	{ .compatible = "sitronix,st7789v" },
    399	{ }
    400};
    401MODULE_DEVICE_TABLE(of, st7789v_of_match);
    402
    403static struct spi_driver st7789v_driver = {
    404	.probe = st7789v_probe,
    405	.remove = st7789v_remove,
    406	.driver = {
    407		.name = "st7789v",
    408		.of_match_table = st7789v_of_match,
    409	},
    410};
    411module_spi_driver(st7789v_driver);
    412
    413MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
    414MODULE_DESCRIPTION("Sitronix st7789v LCD Driver");
    415MODULE_LICENSE("GPL v2");