1 From 9d9b8bd567c30a821c82c27035243536c5234542 Mon Sep 17 00:00:00 2001
2 From: Samuel Holland <samuel@sholland.org>
3 Date: Tue, 29 Mar 2022 22:47:57 -0500
4 Subject: [PATCH 017/117] drm/panel: Add driver for ST7701s DPI LCD panel
6 Signed-off-by: Samuel Holland <samuel@sholland.org>
8 drivers/gpu/drm/panel/Kconfig | 8 +
9 drivers/gpu/drm/panel/Makefile | 1 +
10 .../gpu/drm/panel/panel-sitronix-st7701s.c | 444 ++++++++++++++++++
11 3 files changed, 453 insertions(+)
12 create mode 100644 drivers/gpu/drm/panel/panel-sitronix-st7701s.c
14 --- a/drivers/gpu/drm/panel/Kconfig
15 +++ b/drivers/gpu/drm/panel/Kconfig
16 @@ -608,6 +608,14 @@ config DRM_PANEL_SITRONIX_ST7701
17 ST7701 controller for 480X864 LCD panels with MIPI/RGB/SPI
20 +config DRM_PANEL_SITRONIX_ST7701S
21 + tristate "Sitronix ST7701s panel driver"
23 + depends on BACKLIGHT_CLASS_DEVICE
25 + Say Y here if you want to enable support for the Sitronix
26 + ST7701s controller with a SPI interface.
28 config DRM_PANEL_SITRONIX_ST7703
29 tristate "Sitronix ST7703 based MIPI touchscreen panels"
31 --- a/drivers/gpu/drm/panel/Makefile
32 +++ b/drivers/gpu/drm/panel/Makefile
33 @@ -61,6 +61,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01
34 obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
35 obj-$(CONFIG_DRM_PANEL_SHARP_LS060T1SX01) += panel-sharp-ls060t1sx01.o
36 obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o
37 +obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701S) += panel-sitronix-st7701s.o
38 obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7703) += panel-sitronix-st7703.o
39 obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
40 obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
42 +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701s.c
44 +// SPDX-License-Identifier: GPL-2.0-only
46 + * Copyright (C) 2017 Free Electrons
49 +#include <linux/delay.h>
50 +#include <linux/gpio/consumer.h>
51 +#include <linux/module.h>
52 +#include <linux/spi/spi.h>
54 +#include <video/mipi_display.h>
56 +#include <drm/drm_device.h>
57 +#include <drm/drm_modes.h>
58 +#include <drm/drm_panel.h>
61 + struct drm_panel panel;
62 + struct gpio_desc *reset;
63 + struct spi_device *spi;
67 + ST7789V_COMMAND = 0 << 8,
68 + ST7789V_DATA = 1 << 8,
71 +#define LCD_WRITE_COMMAND(x) (ST7789V_COMMAND | (x))
72 +#define LCD_WRITE_DATA(x) (ST7789V_DATA | (x))
74 +static const u16 st7701s_init_sequence_1[] = {
75 + LCD_WRITE_COMMAND(0xFF),
76 + LCD_WRITE_DATA(0x77),
77 + LCD_WRITE_DATA(0x01),
78 + LCD_WRITE_DATA(0x00),
79 + LCD_WRITE_DATA(0x00),
80 + LCD_WRITE_DATA(0x10),
82 + LCD_WRITE_COMMAND(0xC0),
83 + LCD_WRITE_DATA(0x3B),
84 + LCD_WRITE_DATA(0x00),
86 + LCD_WRITE_COMMAND(0xC1),
87 + LCD_WRITE_DATA(0x0D),
88 + LCD_WRITE_DATA(0x02),
90 + LCD_WRITE_COMMAND(0xC2),
91 + LCD_WRITE_DATA(0x21),
92 + LCD_WRITE_DATA(0x08),
94 + // RGB Interface Setting
95 + // LCD_WRITE_COMMAND(0xC3),
96 + // LCD_WRITE_DATA(0x02),
98 + LCD_WRITE_COMMAND(0xCD),
99 + LCD_WRITE_DATA(0x18),//0F 08-OK D0-D18
101 + LCD_WRITE_COMMAND(0xB0),
102 + LCD_WRITE_DATA(0x00),
103 + LCD_WRITE_DATA(0x11),
104 + LCD_WRITE_DATA(0x18),
105 + LCD_WRITE_DATA(0x0E),
106 + LCD_WRITE_DATA(0x11),
107 + LCD_WRITE_DATA(0x06),
108 + LCD_WRITE_DATA(0x07),
109 + LCD_WRITE_DATA(0x08),
110 + LCD_WRITE_DATA(0x07),
111 + LCD_WRITE_DATA(0x22),
112 + LCD_WRITE_DATA(0x04),
113 + LCD_WRITE_DATA(0x12),
114 + LCD_WRITE_DATA(0x0F),
115 + LCD_WRITE_DATA(0xAA),
116 + LCD_WRITE_DATA(0x31),
117 + LCD_WRITE_DATA(0x18),
119 + LCD_WRITE_COMMAND(0xB1),
120 + LCD_WRITE_DATA(0x00),
121 + LCD_WRITE_DATA(0x11),
122 + LCD_WRITE_DATA(0x19),
123 + LCD_WRITE_DATA(0x0E),
124 + LCD_WRITE_DATA(0x12),
125 + LCD_WRITE_DATA(0x07),
126 + LCD_WRITE_DATA(0x08),
127 + LCD_WRITE_DATA(0x08),
128 + LCD_WRITE_DATA(0x08),
129 + LCD_WRITE_DATA(0x22),
130 + LCD_WRITE_DATA(0x04),
131 + LCD_WRITE_DATA(0x11),
132 + LCD_WRITE_DATA(0x11),
133 + LCD_WRITE_DATA(0xA9),
134 + LCD_WRITE_DATA(0x32),
135 + LCD_WRITE_DATA(0x18),
137 + LCD_WRITE_COMMAND(0xFF),
138 + LCD_WRITE_DATA(0x77),
139 + LCD_WRITE_DATA(0x01),
140 + LCD_WRITE_DATA(0x00),
141 + LCD_WRITE_DATA(0x00),
142 + LCD_WRITE_DATA(0x11),
144 + LCD_WRITE_COMMAND(0xB0),
145 + LCD_WRITE_DATA(0x60),
147 + LCD_WRITE_COMMAND(0xB1),
148 + LCD_WRITE_DATA(0x30),
150 + LCD_WRITE_COMMAND(0xB2),
151 + LCD_WRITE_DATA(0x87),
153 + LCD_WRITE_COMMAND(0xB3),
154 + LCD_WRITE_DATA(0x80),
156 + LCD_WRITE_COMMAND(0xB5),
157 + LCD_WRITE_DATA(0x49),
159 + LCD_WRITE_COMMAND(0xB7),
160 + LCD_WRITE_DATA(0x85),
162 + LCD_WRITE_COMMAND(0xB8),
163 + LCD_WRITE_DATA(0x21),
165 + LCD_WRITE_COMMAND(0xC1),
166 + LCD_WRITE_DATA(0x78),
168 + LCD_WRITE_COMMAND(0xC2),
169 + LCD_WRITE_DATA(0x78),
172 +static const u16 st7701s_init_sequence_2[] = {
173 + LCD_WRITE_COMMAND(0xE0),
174 + LCD_WRITE_DATA(0x00),
175 + LCD_WRITE_DATA(0x1B),
176 + LCD_WRITE_DATA(0x02),
178 + LCD_WRITE_COMMAND(0xE1),
179 + LCD_WRITE_DATA(0x08),
180 + LCD_WRITE_DATA(0xA0),
181 + LCD_WRITE_DATA(0x00),
182 + LCD_WRITE_DATA(0x00),
183 + LCD_WRITE_DATA(0x07),
184 + LCD_WRITE_DATA(0xA0),
185 + LCD_WRITE_DATA(0x00),
186 + LCD_WRITE_DATA(0x00),
187 + LCD_WRITE_DATA(0x00),
188 + LCD_WRITE_DATA(0x44),
189 + LCD_WRITE_DATA(0x44),
191 + LCD_WRITE_COMMAND(0xE2),
192 + LCD_WRITE_DATA(0x11),
193 + LCD_WRITE_DATA(0x11),
194 + LCD_WRITE_DATA(0x44),
195 + LCD_WRITE_DATA(0x44),
196 + LCD_WRITE_DATA(0xED),
197 + LCD_WRITE_DATA(0xA0),
198 + LCD_WRITE_DATA(0x00),
199 + LCD_WRITE_DATA(0x00),
200 + LCD_WRITE_DATA(0xEC),
201 + LCD_WRITE_DATA(0xA0),
202 + LCD_WRITE_DATA(0x00),
203 + LCD_WRITE_DATA(0x00),
205 + LCD_WRITE_COMMAND(0xE3),
206 + LCD_WRITE_DATA(0x00),
207 + LCD_WRITE_DATA(0x00),
208 + LCD_WRITE_DATA(0x11),
209 + LCD_WRITE_DATA(0x11),
211 + LCD_WRITE_COMMAND(0xE4),
212 + LCD_WRITE_DATA(0x44),
213 + LCD_WRITE_DATA(0x44),
215 + LCD_WRITE_COMMAND(0xE5),
216 + LCD_WRITE_DATA(0x0A),
217 + LCD_WRITE_DATA(0xE9),
218 + LCD_WRITE_DATA(0xD8),
219 + LCD_WRITE_DATA(0xA0),
220 + LCD_WRITE_DATA(0x0C),
221 + LCD_WRITE_DATA(0xEB),
222 + LCD_WRITE_DATA(0xD8),
223 + LCD_WRITE_DATA(0xA0),
224 + LCD_WRITE_DATA(0x0E),
225 + LCD_WRITE_DATA(0xED),
226 + LCD_WRITE_DATA(0xD8),
227 + LCD_WRITE_DATA(0xA0),
228 + LCD_WRITE_DATA(0x10),
229 + LCD_WRITE_DATA(0xEF),
230 + LCD_WRITE_DATA(0xD8),
231 + LCD_WRITE_DATA(0xA0),
233 + LCD_WRITE_COMMAND(0xE6),
234 + LCD_WRITE_DATA(0x00),
235 + LCD_WRITE_DATA(0x00),
236 + LCD_WRITE_DATA(0x11),
237 + LCD_WRITE_DATA(0x11),
239 + LCD_WRITE_COMMAND(0xE7),
240 + LCD_WRITE_DATA(0x44),
241 + LCD_WRITE_DATA(0x44),
243 + LCD_WRITE_COMMAND(0xE8),
244 + LCD_WRITE_DATA(0x09),
245 + LCD_WRITE_DATA(0xE8),
246 + LCD_WRITE_DATA(0xD8),
247 + LCD_WRITE_DATA(0xA0),
248 + LCD_WRITE_DATA(0x0B),
249 + LCD_WRITE_DATA(0xEA),
250 + LCD_WRITE_DATA(0xD8),
251 + LCD_WRITE_DATA(0xA0),
252 + LCD_WRITE_DATA(0x0D),
253 + LCD_WRITE_DATA(0xEC),
254 + LCD_WRITE_DATA(0xD8),
255 + LCD_WRITE_DATA(0xA0),
256 + LCD_WRITE_DATA(0x0F),
257 + LCD_WRITE_DATA(0xEE),
258 + LCD_WRITE_DATA(0xD8),
259 + LCD_WRITE_DATA(0xA0),
261 + LCD_WRITE_COMMAND(0xEB),
262 + LCD_WRITE_DATA(0x02),
263 + LCD_WRITE_DATA(0x00),
264 + LCD_WRITE_DATA(0xE4),
265 + LCD_WRITE_DATA(0xE4),
266 + LCD_WRITE_DATA(0x88),
267 + LCD_WRITE_DATA(0x00),
268 + LCD_WRITE_DATA(0x40),
270 + LCD_WRITE_COMMAND(0xEC),
271 + LCD_WRITE_DATA(0x3C),
272 + LCD_WRITE_DATA(0x00),
274 + LCD_WRITE_COMMAND(0xED),
275 + LCD_WRITE_DATA(0xAB),
276 + LCD_WRITE_DATA(0x89),
277 + LCD_WRITE_DATA(0x76),
278 + LCD_WRITE_DATA(0x54),
279 + LCD_WRITE_DATA(0x02),
280 + LCD_WRITE_DATA(0xFF),
281 + LCD_WRITE_DATA(0xFF),
282 + LCD_WRITE_DATA(0xFF),
283 + LCD_WRITE_DATA(0xFF),
284 + LCD_WRITE_DATA(0xFF),
285 + LCD_WRITE_DATA(0xFF),
286 + LCD_WRITE_DATA(0x20),
287 + LCD_WRITE_DATA(0x45),
288 + LCD_WRITE_DATA(0x67),
289 + LCD_WRITE_DATA(0x98),
290 + LCD_WRITE_DATA(0xBA),
292 + LCD_WRITE_COMMAND(0xFF),
293 + LCD_WRITE_DATA(0x77),
294 + LCD_WRITE_DATA(0x01),
295 + LCD_WRITE_DATA(0x00),
296 + LCD_WRITE_DATA(0x00),
297 + LCD_WRITE_DATA(0x00),
299 + LCD_WRITE_COMMAND(MIPI_DCS_SET_PIXEL_FORMAT),
300 + LCD_WRITE_DATA(0x66),
302 + LCD_WRITE_COMMAND(MIPI_DCS_SET_ADDRESS_MODE),
303 + LCD_WRITE_DATA(0x00),
305 + LCD_WRITE_COMMAND(MIPI_DCS_ENTER_INVERT_MODE),
307 + LCD_WRITE_COMMAND(MIPI_DCS_EXIT_SLEEP_MODE),
310 +static const u16 st7701s_enable_sequence[] = {
311 + LCD_WRITE_COMMAND(MIPI_DCS_SET_DISPLAY_ON),
314 +static const u16 st7701s_disable_sequence[] = {
315 + LCD_WRITE_COMMAND(MIPI_DCS_SET_DISPLAY_OFF),
318 +static inline struct st7701s *panel_to_st7701s(struct drm_panel *panel)
320 + return container_of(panel, struct st7701s, panel);
323 +static int st7701s_spi_write(struct st7701s *ctx, const u16 *data, size_t size)
325 + struct spi_transfer xfer = { };
326 + struct spi_message msg;
328 + spi_message_init(&msg);
330 + xfer.tx_buf = data;
331 + xfer.bits_per_word = 9;
334 + spi_message_add_tail(&xfer, &msg);
335 + return spi_sync(ctx->spi, &msg);
338 +static const struct drm_display_mode default_mode = {
341 + .hsync_start = 480 + 60,
342 + .hsync_end = 480 + 60 + 12,
343 + .htotal = 480 + 60 + 12 + 60,
345 + .vsync_start = 480 + 18,
346 + .vsync_end = 480 + 18 + 4,
347 + .vtotal = 480 + 18 + 4 + 18,
350 +static int st7701s_get_modes(struct drm_panel *panel,
351 + struct drm_connector *connector)
353 + struct drm_display_mode *mode;
355 + mode = drm_mode_duplicate(connector->dev, &default_mode);
359 + drm_mode_set_name(mode);
361 + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
362 + drm_mode_probed_add(connector, mode);
364 + connector->display_info.width_mm = 70;
365 + connector->display_info.height_mm = 72;
370 +static int st7701s_prepare(struct drm_panel *panel)
372 + struct st7701s *ctx = panel_to_st7701s(panel);
374 + gpiod_set_value_cansleep(ctx->reset, 1);
377 + gpiod_set_value_cansleep(ctx->reset, 0);
380 + st7701s_spi_write(ctx, st7701s_init_sequence_1,
381 + sizeof(st7701s_init_sequence_1));
384 + st7701s_spi_write(ctx, st7701s_init_sequence_2,
385 + sizeof(st7701s_init_sequence_2));
391 +static int st7701s_enable(struct drm_panel *panel)
393 + struct st7701s *ctx = panel_to_st7701s(panel);
395 + st7701s_spi_write(ctx, st7701s_enable_sequence,
396 + sizeof(st7701s_enable_sequence));
402 +static int st7701s_disable(struct drm_panel *panel)
404 + struct st7701s *ctx = panel_to_st7701s(panel);
406 + st7701s_spi_write(ctx, st7701s_disable_sequence,
407 + sizeof(st7701s_disable_sequence));
412 +static int st7701s_unprepare(struct drm_panel *panel)
417 +static const struct drm_panel_funcs st7701s_drm_funcs = {
418 + .disable = st7701s_disable,
419 + .enable = st7701s_enable,
420 + .get_modes = st7701s_get_modes,
421 + .prepare = st7701s_prepare,
422 + .unprepare = st7701s_unprepare,
425 +static int st7701s_probe(struct spi_device *spi)
427 + struct device *dev = &spi->dev;
428 + struct st7701s *ctx;
431 + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
435 + spi_set_drvdata(spi, ctx);
438 + ctx->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);
439 + if (IS_ERR(ctx->reset)) {
440 + dev_err(&spi->dev, "Couldn't get our reset line\n");
441 + return PTR_ERR(ctx->reset);
444 + drm_panel_init(&ctx->panel, dev, &st7701s_drm_funcs,
445 + DRM_MODE_CONNECTOR_DPI);
447 + ret = drm_panel_of_backlight(&ctx->panel);
451 + drm_panel_add(&ctx->panel);
456 +static void st7701s_remove(struct spi_device *spi)
458 + struct st7701s *ctx = spi_get_drvdata(spi);
460 + drm_panel_remove(&ctx->panel);
463 +static const struct of_device_id st7701s_of_match[] = {
464 + { .compatible = "sitronix,st7701s" },
467 +MODULE_DEVICE_TABLE(of, st7701s_of_match);
469 +static const struct spi_device_id st7701s_ids[] = {
473 +MODULE_DEVICE_TABLE(spi, st7701s_ids);
475 +static struct spi_driver st7701s_driver = {
476 + .probe = st7701s_probe,
477 + .remove = st7701s_remove,
480 + .of_match_table = st7701s_of_match,
483 +module_spi_driver(st7701s_driver);
485 +MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
486 +MODULE_DESCRIPTION("Sitronix ST7701s LCD Driver");
487 +MODULE_LICENSE("GPL v2");