xref: /linux/drivers/gpu/drm/sitronix/st7571.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Driver for Sitronix ST7571, a 4 level gray scale dot matrix LCD controller
4  *
5  * Copyright (C) 2025 Marcus Folkesson <marcus.folkesson@gmail.com>
6  */
7 
8 #include <linux/bitfield.h>
9 #include <linux/delay.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/i2c.h>
12 #include <linux/module.h>
13 #include <linux/regmap.h>
14 
15 #include <drm/clients/drm_client_setup.h>
16 #include <drm/drm_atomic.h>
17 #include <drm/drm_atomic_helper.h>
18 #include <drm/drm_connector.h>
19 #include <drm/drm_crtc_helper.h>
20 #include <drm/drm_damage_helper.h>
21 #include <drm/drm_drv.h>
22 #include <drm/drm_encoder.h>
23 #include <drm/drm_fb_helper.h>
24 #include <drm/drm_fbdev_shmem.h>
25 #include <drm/drm_fourcc.h>
26 #include <drm/drm_framebuffer.h>
27 #include <drm/drm_gem_atomic_helper.h>
28 #include <drm/drm_gem_framebuffer_helper.h>
29 #include <drm/drm_gem_shmem_helper.h>
30 #include <drm/drm_modeset_helper_vtables.h>
31 #include <drm/drm_module.h>
32 #include <drm/drm_plane.h>
33 #include <drm/drm_probe_helper.h>
34 
35 #include <video/display_timing.h>
36 #include <video/of_display_timing.h>
37 
38 #include "st7571.h"
39 
40 #define ST7571_COMMAND_MODE			(0x00)
41 #define ST7571_DATA_MODE			(0x40)
42 
43 /* Normal mode command set */
44 #define ST7571_DISPLAY_OFF			(0xae)
45 #define ST7571_DISPLAY_ON			(0xaf)
46 #define ST7571_OSC_ON				(0xab)
47 #define ST7571_SET_COLUMN_LSB(c)		(0x00 | FIELD_PREP(GENMASK(3, 0), (c)))
48 #define ST7571_SET_COLUMN_MSB(c)		(0x10 | FIELD_PREP(GENMASK(2, 0), (c) >> 4))
49 #define ST7571_SET_COM0_LSB(x)			(FIELD_PREP(GENMASK(6, 0), (x)))
50 #define ST7571_SET_COM0_MSB			(0x44)
51 #define ST7571_SET_COM_SCAN_DIR(d)		(0xc0 | FIELD_PREP(GENMASK(3, 3), (d)))
52 #define ST7571_SET_CONTRAST_LSB(c)		(FIELD_PREP(GENMASK(5, 0), (c)))
53 #define ST7571_SET_CONTRAST_MSB			(0x81)
54 #define ST7571_SET_DISPLAY_DUTY_LSB(d)		(FIELD_PREP(GENMASK(7, 0), (d)))
55 #define ST7571_SET_DISPLAY_DUTY_MSB		(0x48)
56 #define ST7571_SET_ENTIRE_DISPLAY_ON(p)		(0xa4 | FIELD_PREP(GENMASK(0, 0), (p)))
57 #define ST7571_SET_LCD_BIAS(b)			(0x50 | FIELD_PREP(GENMASK(2, 0), (b)))
58 #define ST7571_SET_MODE_LSB(m)			(FIELD_PREP(GENMASK(7, 2), (m)))
59 #define ST7571_SET_MODE_MSB			(0x38)
60 #define ST7571_SET_PAGE(p)			(0xb0 | FIELD_PREP(GENMASK(3, 0), (p)))
61 #define ST7571_SET_POWER(p)			(0x28 | FIELD_PREP(GENMASK(2, 0), (p)))
62 #define ST7571_SET_REGULATOR_REG(r)		(0x20 | FIELD_PREP(GENMASK(2, 0), (r)))
63 #define ST7571_SET_REVERSE(r)			(0xa6 | FIELD_PREP(GENMASK(0, 0), (r)))
64 #define ST7571_SET_SEG_SCAN_DIR(d)		(0xa0 | FIELD_PREP(GENMASK(0, 0), (d)))
65 #define ST7571_SET_START_LINE_LSB(l)		(FIELD_PREP(GENMASK(6, 0), (l)))
66 #define ST7571_SET_START_LINE_MSB		(0x40)
67 
68 /* Extension command set 3 */
69 #define ST7571_COMMAND_SET_3			(0x7b)
70 #define ST7571_SET_COLOR_MODE(c)		(0x10 | FIELD_PREP(GENMASK(0, 0), (c)))
71 #define ST7571_COMMAND_SET_NORMAL		(0x00)
72 
73 /* ST7567 commands */
74 #define ST7567_SET_LCD_BIAS(m) (0xa2 | FIELD_PREP(GENMASK(0, 0), (m)))
75 
76 #define ST7571_PAGE_HEIGHT 8
77 
78 #define DRIVER_NAME "st7571"
79 #define DRIVER_DESC "ST7571 DRM driver"
80 #define DRIVER_MAJOR 1
81 #define DRIVER_MINOR 0
82 
83 static inline struct st7571_device *drm_to_st7571(struct drm_device *drm)
84 {
85 	return container_of(drm, struct st7571_device, drm);
86 }
87 
88 static int st7571_send_command_list(struct st7571_device *st7571,
89 				    const u8 *cmd_list, size_t len)
90 {
91 	int ret;
92 
93 	for (int i = 0; i < len; i++) {
94 		ret = regmap_write(st7571->regmap, ST7571_COMMAND_MODE, cmd_list[i]);
95 		if (ret < 0)
96 			return ret;
97 	}
98 
99 	return ret;
100 }
101 
102 static inline u8 st7571_transform_xy(const char *p, int x, int y, u8 bpp)
103 {
104 	int xrest = x % 8;
105 	u8 result = 0;
106 	u8 row_len = 16 * bpp;
107 
108 	/*
109 	 * Transforms an (x, y) pixel coordinate into a vertical 8-bit
110 	 * column from the framebuffer. It calculates the corresponding byte in the
111 	 * framebuffer, extracts the bit at the given x position across 8 consecutive
112 	 * rows, and packs those bits into a single byte.
113 	 *
114 	 * Return an 8-bit value representing a vertical column of pixels.
115 	 */
116 	x = x / 8;
117 	y = (y / 8) * 8;
118 
119 	for (int i = 0; i < 8; i++) {
120 		int row_idx = y + i;
121 		u8 byte = p[row_idx * row_len + x];
122 		u8 bit = (byte >> xrest) & 1;
123 
124 		result |= (bit << i);
125 	}
126 
127 	return result;
128 }
129 
130 static int st7571_set_position(struct st7571_device *st7571, int x, int y)
131 {
132 	u8 cmd_list[] = {
133 		ST7571_SET_COLUMN_LSB(x),
134 		ST7571_SET_COLUMN_MSB(x),
135 		ST7571_SET_PAGE(y / ST7571_PAGE_HEIGHT),
136 	};
137 
138 	return st7571_send_command_list(st7571, cmd_list, ARRAY_SIZE(cmd_list));
139 }
140 
141 static int st7571_fb_clear_screen(struct st7571_device *st7571)
142 {
143 	u32 npixels = st7571->ncols * round_up(st7571->nlines, ST7571_PAGE_HEIGHT) * st7571->bpp;
144 	char pixelvalue = 0x00;
145 
146 	st7571_set_position(st7571, 0, 0);
147 	for (int i = 0; i < npixels; i++)
148 		regmap_bulk_write(st7571->regmap, ST7571_DATA_MODE, &pixelvalue, 1);
149 
150 	return 0;
151 }
152 
153 static void st7571_prepare_buffer_monochrome(struct st7571_device *st7571,
154 					     const struct iosys_map *vmap,
155 					     struct drm_framebuffer *fb,
156 					     struct drm_rect *rect,
157 					     struct drm_format_conv_state *fmtcnv_state)
158 {
159 	unsigned int dst_pitch;
160 	struct iosys_map dst;
161 	u32 size;
162 
163 	switch (fb->format->format) {
164 	case DRM_FORMAT_XRGB8888:
165 		dst_pitch = DIV_ROUND_UP(drm_rect_width(rect), 8);
166 		iosys_map_set_vaddr(&dst, st7571->hwbuf);
167 
168 		drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
169 		break;
170 
171 	case DRM_FORMAT_R1:
172 		size = (rect->x2 - rect->x1) * (rect->y2 - rect->y1) / 8;
173 		memcpy(st7571->hwbuf, vmap->vaddr, size);
174 		break;
175 	}
176 }
177 
178 static void st7571_prepare_buffer_grayscale(struct st7571_device *st7571,
179 					    const struct iosys_map *vmap,
180 					    struct drm_framebuffer *fb,
181 					    struct drm_rect *rect,
182 					    struct drm_format_conv_state *fmtcnv_state)
183 {
184 	u32 size = (rect->x2 - rect->x1) * (rect->y2 - rect->y1) / 8;
185 	unsigned int dst_pitch;
186 	struct iosys_map dst;
187 
188 	switch (fb->format->format) {
189 	case DRM_FORMAT_XRGB8888:
190 		dst_pitch = DIV_ROUND_UP(drm_rect_width(rect), 4);
191 		iosys_map_set_vaddr(&dst, st7571->hwbuf);
192 
193 		drm_fb_xrgb8888_to_gray2(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
194 		break;
195 
196 	case DRM_FORMAT_R1:
197 		size = (rect->x2 - rect->x1) * (rect->y2 - rect->y1) / 8;
198 		memcpy(st7571->hwbuf, vmap->vaddr, size);
199 		break;
200 
201 	case DRM_FORMAT_R2:
202 		size = (rect->x2 - rect->x1) * (rect->y2 - rect->y1) / 4;
203 		memcpy(st7571->hwbuf, vmap->vaddr, size);
204 		break;
205 	}
206 }
207 
208 static int st7571_fb_update_rect_monochrome(struct drm_framebuffer *fb, struct drm_rect *rect)
209 {
210 	struct st7571_device *st7571 = drm_to_st7571(fb->dev);
211 	char *row = st7571->row;
212 
213 	/* Align y to display page boundaries */
214 	rect->y1 = round_down(rect->y1, ST7571_PAGE_HEIGHT);
215 	rect->y2 = min_t(unsigned int, round_up(rect->y2, ST7571_PAGE_HEIGHT), st7571->nlines);
216 
217 	for (int y = rect->y1; y < rect->y2; y += ST7571_PAGE_HEIGHT) {
218 		for (int x = rect->x1; x < rect->x2; x++)
219 			row[x] = st7571_transform_xy(st7571->hwbuf, x, y, 1);
220 
221 		st7571_set_position(st7571, rect->x1, y);
222 
223 		/* TODO: Investige why we can't write multiple bytes at once */
224 		for (int x = rect->x1; x < rect->x2; x++)
225 			regmap_bulk_write(st7571->regmap, ST7571_DATA_MODE, row + x, 1);
226 	}
227 
228 	return 0;
229 }
230 
231 static int st7571_fb_update_rect_grayscale(struct drm_framebuffer *fb, struct drm_rect *rect)
232 {
233 	struct st7571_device *st7571 = drm_to_st7571(fb->dev);
234 	u32 format = fb->format->format;
235 	char *row = st7571->row;
236 	int x1;
237 	int x2;
238 
239 	/* Align y to display page boundaries */
240 	rect->y1 = round_down(rect->y1, ST7571_PAGE_HEIGHT);
241 	rect->y2 = min_t(unsigned int, round_up(rect->y2, ST7571_PAGE_HEIGHT), st7571->nlines);
242 
243 	switch (format) {
244 	case DRM_FORMAT_R1:
245 		x1 = rect->x1 * 1;
246 		x2 = rect->x2 * 1;
247 		break;
248 	case DRM_FORMAT_R2:
249 		fallthrough;
250 	case DRM_FORMAT_XRGB8888:
251 		x1 = rect->x1 * 2;
252 		x2 = rect->x2 * 2;
253 		break;
254 	}
255 
256 	for (int y = rect->y1; y < rect->y2; y += ST7571_PAGE_HEIGHT) {
257 		for (int x = x1; x < x2; x++)
258 			row[x] = st7571_transform_xy(st7571->hwbuf, x, y, 2);
259 
260 		st7571_set_position(st7571, rect->x1, y);
261 
262 		/* TODO: Investige why we can't write multiple bytes at once */
263 		for (int x = x1; x < x2; x++) {
264 			regmap_bulk_write(st7571->regmap, ST7571_DATA_MODE, row + x, 1);
265 
266 			/*
267 			 * As the display supports grayscale, all pixels must be written as two bits
268 			 * even if the format is monochrome.
269 			 *
270 			 * The bit values maps to the following grayscale:
271 			 * 0 0 = Black
272 			 * 0 1 = Dark gray
273 			 * 1 0 = Light gray
274 			 * 1 1 = White
275 			 *
276 			 * For monochrome formats, write the same value twice to get
277 			 * either a black or white pixel.
278 			 */
279 			if (format == DRM_FORMAT_R1)
280 				regmap_bulk_write(st7571->regmap, ST7571_DATA_MODE, row + x, 1);
281 		}
282 	}
283 
284 	return 0;
285 }
286 
287 static int st7571_connector_get_modes(struct drm_connector *conn)
288 {
289 	struct st7571_device *st7571 = drm_to_st7571(conn->dev);
290 
291 	return drm_connector_helper_get_modes_fixed(conn, &st7571->mode);
292 }
293 
294 static const struct drm_connector_helper_funcs st7571_connector_helper_funcs = {
295 	.get_modes = st7571_connector_get_modes,
296 };
297 
298 static const struct st7571_panel_format st7571_monochrome = {
299 	.prepare_buffer = st7571_prepare_buffer_monochrome,
300 	.update_rect = st7571_fb_update_rect_monochrome,
301 	.mode = ST7571_COLOR_MODE_BLACKWHITE,
302 	.formats = {
303 		DRM_FORMAT_XRGB8888,
304 		DRM_FORMAT_R1,
305 	},
306 	.nformats = 2,
307 };
308 
309 static const struct st7571_panel_format st7571_grayscale = {
310 	.prepare_buffer = st7571_prepare_buffer_grayscale,
311 	.update_rect = st7571_fb_update_rect_grayscale,
312 	.mode = ST7571_COLOR_MODE_GRAY,
313 	.formats = {
314 		DRM_FORMAT_XRGB8888,
315 		DRM_FORMAT_R1,
316 		DRM_FORMAT_R2,
317 	},
318 	.nformats = 3,
319 };
320 
321 static const u64 st7571_primary_plane_fmtmods[] = {
322 	DRM_FORMAT_MOD_LINEAR,
323 	DRM_FORMAT_MOD_INVALID
324 };
325 
326 static int st7571_primary_plane_helper_atomic_check(struct drm_plane *plane,
327 						    struct drm_atomic_state *state)
328 {
329 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
330 	struct drm_crtc *new_crtc = new_plane_state->crtc;
331 	struct drm_crtc_state *new_crtc_state = NULL;
332 
333 	if (new_crtc)
334 		new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
335 
336 	return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
337 						   DRM_PLANE_NO_SCALING,
338 						   DRM_PLANE_NO_SCALING,
339 						   false, false);
340 }
341 
342 static void st7571_primary_plane_helper_atomic_update(struct drm_plane *plane,
343 						      struct drm_atomic_state *state)
344 {
345 	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
346 	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
347 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
348 	struct drm_framebuffer *fb = plane_state->fb;
349 	struct drm_atomic_helper_damage_iter iter;
350 	struct drm_device *drm = plane->dev;
351 	struct drm_rect damage;
352 	struct st7571_device *st7571 = drm_to_st7571(plane->dev);
353 	int ret, idx;
354 
355 	if (!fb)
356 		return; /* no framebuffer; plane is disabled */
357 
358 	ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
359 	if (ret)
360 		return;
361 
362 	if (!drm_dev_enter(drm, &idx))
363 		goto out_drm_gem_fb_end_cpu_access;
364 
365 	drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
366 	drm_atomic_for_each_plane_damage(&iter, &damage) {
367 		st7571->pformat->prepare_buffer(st7571,
368 						&shadow_plane_state->data[0],
369 						fb, &damage,
370 						&shadow_plane_state->fmtcnv_state);
371 
372 		st7571->pformat->update_rect(fb, &damage);
373 	}
374 
375 	drm_dev_exit(idx);
376 
377 out_drm_gem_fb_end_cpu_access:
378 	drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
379 }
380 
381 static void st7571_primary_plane_helper_atomic_disable(struct drm_plane *plane,
382 						       struct drm_atomic_state *state)
383 {
384 	struct drm_device *drm = plane->dev;
385 	struct st7571_device *st7571 = drm_to_st7571(plane->dev);
386 	int idx;
387 
388 	if (!drm_dev_enter(drm, &idx))
389 		return;
390 
391 	st7571_fb_clear_screen(st7571);
392 	drm_dev_exit(idx);
393 }
394 
395 static const struct drm_plane_helper_funcs st7571_primary_plane_helper_funcs = {
396 	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
397 	.atomic_check = st7571_primary_plane_helper_atomic_check,
398 	.atomic_update = st7571_primary_plane_helper_atomic_update,
399 	.atomic_disable = st7571_primary_plane_helper_atomic_disable,
400 };
401 
402 static const struct drm_plane_funcs st7571_primary_plane_funcs = {
403 	.update_plane = drm_atomic_helper_update_plane,
404 	.disable_plane = drm_atomic_helper_disable_plane,
405 	.destroy = drm_plane_cleanup,
406 	DRM_GEM_SHADOW_PLANE_FUNCS,
407 };
408 
409 /*
410  * CRTC
411  */
412 
413 static enum drm_mode_status st7571_crtc_mode_valid(struct drm_crtc *crtc,
414 						   const struct drm_display_mode *mode)
415 {
416 	struct st7571_device *st7571 = drm_to_st7571(crtc->dev);
417 
418 	return drm_crtc_helper_mode_valid_fixed(crtc, mode, &st7571->mode);
419 }
420 
421 static const struct drm_crtc_helper_funcs st7571_crtc_helper_funcs = {
422 	.atomic_check = drm_crtc_helper_atomic_check,
423 	.mode_valid = st7571_crtc_mode_valid,
424 };
425 
426 static const struct drm_crtc_funcs st7571_crtc_funcs = {
427 	.reset = drm_atomic_helper_crtc_reset,
428 	.destroy = drm_crtc_cleanup,
429 	.set_config = drm_atomic_helper_set_config,
430 	.page_flip = drm_atomic_helper_page_flip,
431 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
432 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
433 };
434 
435 /*
436  * Encoder
437  */
438 
439 static void st7571_encoder_atomic_enable(struct drm_encoder *encoder,
440 					 struct drm_atomic_state *state)
441 {
442 	struct drm_device *drm = encoder->dev;
443 	struct st7571_device *st7571 = drm_to_st7571(drm);
444 	u8 command = ST7571_DISPLAY_ON;
445 	int ret;
446 
447 	ret = st7571->pdata->init(st7571);
448 	if (ret)
449 		return;
450 
451 	st7571_send_command_list(st7571, &command, 1);
452 }
453 
454 static void st7571_encoder_atomic_disable(struct drm_encoder *encoder,
455 					  struct drm_atomic_state *state)
456 {
457 	struct drm_device *drm = encoder->dev;
458 	struct st7571_device *st7571 = drm_to_st7571(drm);
459 	u8 command = ST7571_DISPLAY_OFF;
460 
461 	st7571_send_command_list(st7571, &command, 1);
462 }
463 
464 static const struct drm_encoder_funcs st7571_encoder_funcs = {
465 	.destroy = drm_encoder_cleanup,
466 
467 };
468 
469 static const struct drm_encoder_helper_funcs st7571_encoder_helper_funcs = {
470 	.atomic_enable = st7571_encoder_atomic_enable,
471 	.atomic_disable = st7571_encoder_atomic_disable,
472 };
473 
474 /*
475  * Connector
476  */
477 
478 static const struct drm_connector_funcs st7571_connector_funcs = {
479 	.reset = drm_atomic_helper_connector_reset,
480 	.fill_modes = drm_helper_probe_single_connector_modes,
481 	.destroy = drm_connector_cleanup,
482 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
483 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
484 };
485 
486 static const struct drm_mode_config_funcs st7571_mode_config_funcs = {
487 	.fb_create = drm_gem_fb_create_with_dirty,
488 	.atomic_check = drm_atomic_helper_check,
489 	.atomic_commit = drm_atomic_helper_commit,
490 };
491 
492 static struct drm_display_mode st7571_mode(struct st7571_device *st7571)
493 {
494 	struct drm_display_mode mode = {
495 		DRM_SIMPLE_MODE(st7571->ncols, st7571->nlines,
496 				st7571->width_mm, st7571->height_mm),
497 	};
498 
499 	return mode;
500 }
501 
502 static int st7571_mode_config_init(struct st7571_device *st7571)
503 {
504 	struct drm_device *drm = &st7571->drm;
505 	const struct st7571_panel_constraints *constraints = &st7571->pdata->constraints;
506 	int ret;
507 
508 	ret = drmm_mode_config_init(drm);
509 	if (ret)
510 		return ret;
511 
512 	drm->mode_config.min_width = constraints->min_ncols;
513 	drm->mode_config.min_height = constraints->min_nlines;
514 	drm->mode_config.max_width = constraints->max_ncols;
515 	drm->mode_config.max_height = constraints->max_nlines;
516 	drm->mode_config.preferred_depth = 24;
517 	drm->mode_config.funcs = &st7571_mode_config_funcs;
518 
519 	return 0;
520 }
521 
522 static int st7571_plane_init(struct st7571_device *st7571,
523 			     const struct st7571_panel_format *pformat)
524 {
525 	struct drm_plane *primary_plane = &st7571->primary_plane;
526 	struct drm_device *drm = &st7571->drm;
527 	int ret;
528 
529 	ret = drm_universal_plane_init(drm, primary_plane, 0,
530 				       &st7571_primary_plane_funcs,
531 				       pformat->formats,
532 				       pformat->nformats,
533 				       st7571_primary_plane_fmtmods,
534 				       DRM_PLANE_TYPE_PRIMARY, NULL);
535 	if (ret)
536 		return ret;
537 
538 	drm_plane_helper_add(primary_plane, &st7571_primary_plane_helper_funcs);
539 	drm_plane_enable_fb_damage_clips(primary_plane);
540 
541 	return 0;
542 }
543 
544 static int st7571_crtc_init(struct st7571_device *st7571)
545 {
546 	struct drm_plane *primary_plane = &st7571->primary_plane;
547 	struct drm_crtc *crtc = &st7571->crtc;
548 	struct drm_device *drm = &st7571->drm;
549 	int ret;
550 
551 	ret = drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
552 					&st7571_crtc_funcs, NULL);
553 	if (ret)
554 		return ret;
555 
556 	drm_crtc_helper_add(crtc, &st7571_crtc_helper_funcs);
557 
558 	return 0;
559 }
560 
561 static int st7571_encoder_init(struct st7571_device *st7571)
562 {
563 	struct drm_encoder *encoder = &st7571->encoder;
564 	struct drm_crtc *crtc = &st7571->crtc;
565 	struct drm_device *drm = &st7571->drm;
566 	int ret;
567 
568 	ret = drm_encoder_init(drm, encoder, &st7571_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
569 	if (ret)
570 		return ret;
571 
572 	drm_encoder_helper_add(encoder, &st7571_encoder_helper_funcs);
573 
574 	encoder->possible_crtcs = drm_crtc_mask(crtc);
575 
576 	return 0;
577 }
578 
579 static int st7571_connector_init(struct st7571_device *st7571)
580 {
581 	struct drm_connector *connector = &st7571->connector;
582 	struct drm_encoder *encoder = &st7571->encoder;
583 	struct drm_device *drm = &st7571->drm;
584 	int ret;
585 
586 	ret = drm_connector_init(drm, connector, &st7571_connector_funcs,
587 				 DRM_MODE_CONNECTOR_Unknown);
588 	if (ret)
589 		return ret;
590 
591 	drm_connector_helper_add(connector, &st7571_connector_helper_funcs);
592 
593 	return drm_connector_attach_encoder(connector, encoder);
594 }
595 
596 DEFINE_DRM_GEM_FOPS(st7571_fops);
597 
598 static const struct drm_driver st7571_driver = {
599 	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
600 
601 	.name		 = DRIVER_NAME,
602 	.desc		 = DRIVER_DESC,
603 	.major		 = DRIVER_MAJOR,
604 	.minor		 = DRIVER_MINOR,
605 
606 	.fops		 = &st7571_fops,
607 	DRM_GEM_SHMEM_DRIVER_OPS,
608 	DRM_FBDEV_SHMEM_DRIVER_OPS,
609 };
610 
611 static int st7571_validate_parameters(struct st7571_device *st7571)
612 {
613 	struct device *dev = st7571->dev;
614 	const struct st7571_panel_constraints *constraints = &st7571->pdata->constraints;
615 
616 	if (st7571->width_mm  == 0) {
617 		dev_err(dev, "Invalid panel width\n");
618 		return -EINVAL;
619 	}
620 
621 	if (st7571->height_mm == 0) {
622 		dev_err(dev, "Invalid panel height\n");
623 		return -EINVAL;
624 	}
625 
626 	if (st7571->nlines < constraints->min_nlines ||
627 	    st7571->nlines > constraints->max_nlines) {
628 		dev_err(dev, "Invalid timing configuration.\n");
629 		return -EINVAL;
630 	}
631 
632 	if (st7571->startline + st7571->nlines > constraints->max_nlines) {
633 		dev_err(dev, "Invalid timing configuration.\n");
634 		return -EINVAL;
635 	}
636 
637 	if (st7571->ncols < constraints->min_ncols ||
638 	    st7571->ncols > constraints->max_ncols) {
639 		dev_err(dev, "Invalid timing configuration.\n");
640 		return -EINVAL;
641 	}
642 
643 	if (st7571->grayscale && !constraints->support_grayscale) {
644 		dev_err(dev, "Grayscale not supported\n");
645 		return -EINVAL;
646 	}
647 
648 	return 0;
649 }
650 
651 static int st7567_parse_dt(struct st7571_device *st7567)
652 {
653 	struct device *dev = st7567->dev;
654 	struct device_node *np = dev->of_node;
655 	struct display_timing dt;
656 	int ret;
657 
658 	ret = of_get_display_timing(np, "panel-timing", &dt);
659 	if (ret) {
660 		dev_err(dev, "Failed to get display timing from DT\n");
661 		return ret;
662 	}
663 
664 	of_property_read_u32(np, "width-mm", &st7567->width_mm);
665 	of_property_read_u32(np, "height-mm", &st7567->height_mm);
666 	st7567->inverted = of_property_read_bool(np, "sitronix,inverted");
667 
668 	st7567->pformat = &st7571_monochrome;
669 	st7567->bpp = 1;
670 
671 	st7567->startline = dt.vfront_porch.typ;
672 	st7567->nlines = dt.vactive.typ;
673 	st7567->ncols = dt.hactive.typ;
674 
675 	return 0;
676 }
677 
678 static int st7571_parse_dt(struct st7571_device *st7571)
679 {
680 	struct device *dev = st7571->dev;
681 	struct device_node *np = dev->of_node;
682 	struct display_timing dt;
683 	int ret;
684 
685 	ret = of_get_display_timing(np, "panel-timing", &dt);
686 	if (ret) {
687 		dev_err(dev, "Failed to get display timing from DT\n");
688 		return ret;
689 	}
690 
691 	of_property_read_u32(np, "width-mm", &st7571->width_mm);
692 	of_property_read_u32(np, "height-mm", &st7571->height_mm);
693 	st7571->grayscale = of_property_read_bool(np, "sitronix,grayscale");
694 	st7571->inverted = of_property_read_bool(np, "sitronix,inverted");
695 
696 	if (st7571->grayscale) {
697 		st7571->pformat = &st7571_grayscale;
698 		st7571->bpp = 2;
699 	} else {
700 		st7571->pformat = &st7571_monochrome;
701 		st7571->bpp = 1;
702 	}
703 
704 	st7571->startline = dt.vfront_porch.typ;
705 	st7571->nlines = dt.vactive.typ;
706 	st7571->ncols = dt.hactive.typ;
707 
708 	st7571->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
709 	if (IS_ERR(st7571->reset))
710 		return dev_err_probe(dev, PTR_ERR(st7571->reset),
711 				     "Failed to get reset gpio\n");
712 
713 	return 0;
714 }
715 
716 static void st7571_reset(struct st7571_device *st7571)
717 {
718 	gpiod_set_value_cansleep(st7571->reset, 1);
719 	fsleep(20);
720 	gpiod_set_value_cansleep(st7571->reset, 0);
721 }
722 
723 static int st7567_lcd_init(struct st7571_device *st7567)
724 {
725 	/*
726 	 * Most of the initialization sequence is taken directly from the
727 	 * referential initial code in the ST7567 datasheet.
728 	 */
729 	u8 commands[] = {
730 		ST7571_DISPLAY_OFF,
731 
732 		ST7567_SET_LCD_BIAS(1),
733 
734 		ST7571_SET_SEG_SCAN_DIR(0),
735 		ST7571_SET_COM_SCAN_DIR(1),
736 
737 		ST7571_SET_REGULATOR_REG(4),
738 		ST7571_SET_CONTRAST_MSB,
739 		ST7571_SET_CONTRAST_LSB(0x20),
740 
741 		ST7571_SET_START_LINE_MSB,
742 		ST7571_SET_START_LINE_LSB(st7567->startline),
743 
744 		ST7571_SET_POWER(0x4),	/* Power Control, VC: ON, VR: OFF, VF: OFF */
745 		ST7571_SET_POWER(0x6),	/* Power Control, VC: ON, VR: ON, VF: OFF */
746 		ST7571_SET_POWER(0x7),	/* Power Control, VC: ON, VR: ON, VF: ON */
747 
748 		ST7571_SET_REVERSE(st7567->inverted ? 1 : 0),
749 		ST7571_SET_ENTIRE_DISPLAY_ON(0),
750 	};
751 
752 	return st7571_send_command_list(st7567, commands, ARRAY_SIZE(commands));
753 }
754 
755 static int st7571_lcd_init(struct st7571_device *st7571)
756 {
757 	/*
758 	 * Most of the initialization sequence is taken directly from the
759 	 * referential initial code in the ST7571 datasheet.
760 	 */
761 	u8 commands[] = {
762 		ST7571_DISPLAY_OFF,
763 
764 		ST7571_SET_MODE_MSB,
765 		ST7571_SET_MODE_LSB(0x2e),
766 
767 		ST7571_SET_SEG_SCAN_DIR(0),
768 		ST7571_SET_COM_SCAN_DIR(1),
769 
770 		ST7571_SET_COM0_MSB,
771 		ST7571_SET_COM0_LSB(0x00),
772 
773 		ST7571_SET_START_LINE_MSB,
774 		ST7571_SET_START_LINE_LSB(st7571->startline),
775 
776 		ST7571_OSC_ON,
777 		ST7571_SET_REGULATOR_REG(5),
778 		ST7571_SET_CONTRAST_MSB,
779 		ST7571_SET_CONTRAST_LSB(0x33),
780 		ST7571_SET_LCD_BIAS(0x04),
781 		ST7571_SET_DISPLAY_DUTY_MSB,
782 		ST7571_SET_DISPLAY_DUTY_LSB(st7571->nlines),
783 
784 		ST7571_SET_POWER(0x4),	/* Power Control, VC: ON, VR: OFF, VF: OFF */
785 		ST7571_SET_POWER(0x6),	/* Power Control, VC: ON, VR: ON, VF: OFF */
786 		ST7571_SET_POWER(0x7),	/* Power Control, VC: ON, VR: ON, VF: ON */
787 
788 		ST7571_COMMAND_SET_3,
789 		ST7571_SET_COLOR_MODE(st7571->pformat->mode),
790 		ST7571_COMMAND_SET_NORMAL,
791 
792 		ST7571_SET_REVERSE(st7571->inverted ? 1 : 0),
793 		ST7571_SET_ENTIRE_DISPLAY_ON(0),
794 	};
795 
796 	/* Perform a reset before initializing the controller */
797 	st7571_reset(st7571);
798 
799 	return st7571_send_command_list(st7571, commands, ARRAY_SIZE(commands));
800 }
801 
802 struct st7571_device *st7571_probe(struct device *dev,
803 				   struct regmap *regmap)
804 {
805 	struct st7571_device *st7571;
806 	struct drm_device *drm;
807 	int ret;
808 
809 	st7571 = devm_drm_dev_alloc(dev, &st7571_driver,
810 				    struct st7571_device, drm);
811 	if (IS_ERR(st7571))
812 		return st7571;
813 
814 	drm = &st7571->drm;
815 	st7571->dev = dev;
816 	st7571->pdata = device_get_match_data(st7571->dev);
817 
818 	ret = st7571->pdata->parse_dt(st7571);
819 	if (ret)
820 		return ERR_PTR(ret);
821 
822 	ret = st7571_validate_parameters(st7571);
823 	if (ret)
824 		return ERR_PTR(ret);
825 
826 	st7571->mode = st7571_mode(st7571);
827 	st7571->regmap = regmap;
828 
829 	st7571->hwbuf = devm_kzalloc(st7571->dev,
830 				     (st7571->nlines * st7571->ncols * st7571->bpp) / 8,
831 				     GFP_KERNEL);
832 	if (!st7571->hwbuf)
833 		return ERR_PTR(-ENOMEM);
834 
835 	st7571->row = devm_kzalloc(st7571->dev,
836 				   (st7571->ncols * st7571->bpp),
837 				   GFP_KERNEL);
838 	if (!st7571->row)
839 		return ERR_PTR(-ENOMEM);
840 
841 	ret = st7571_mode_config_init(st7571);
842 	if (ret) {
843 		dev_err(st7571->dev, "Failed to initialize mode config\n");
844 		return ERR_PTR(ret);
845 	}
846 
847 	ret = st7571_plane_init(st7571, st7571->pformat);
848 	if (ret) {
849 		dev_err(st7571->dev, "Failed to initialize primary plane\n");
850 		return ERR_PTR(ret);
851 	}
852 
853 	ret = st7571_crtc_init(st7571);
854 	if (ret < 0) {
855 		dev_err(st7571->dev, "Failed to initialize CRTC\n");
856 		return ERR_PTR(ret);
857 	}
858 
859 	ret = st7571_encoder_init(st7571);
860 	if (ret < 0) {
861 		dev_err(st7571->dev, "Failed to initialize encoder\n");
862 		return ERR_PTR(ret);
863 	}
864 
865 	ret = st7571_connector_init(st7571);
866 	if (ret < 0) {
867 		dev_err(st7571->dev, "Failed to initialize connector\n");
868 		return ERR_PTR(ret);
869 	}
870 
871 	drm_mode_config_reset(drm);
872 
873 	ret = drm_dev_register(drm, 0);
874 	if (ret) {
875 		dev_err(st7571->dev, "Failed to register DRM device\n");
876 		return ERR_PTR(ret);
877 	}
878 
879 	drm_client_setup(drm, NULL);
880 	return st7571;
881 }
882 EXPORT_SYMBOL_GPL(st7571_probe);
883 
884 void st7571_remove(struct st7571_device *st7571)
885 {
886 	drm_dev_unplug(&st7571->drm);
887 }
888 EXPORT_SYMBOL_GPL(st7571_remove);
889 
890 const struct st7571_panel_data st7567_config = {
891 	.init = st7567_lcd_init,
892 	.parse_dt = st7567_parse_dt,
893 	.constraints = {
894 		.min_nlines = 1,
895 		.max_nlines = 64,
896 		.min_ncols = 128,
897 		.max_ncols = 128,
898 		.support_grayscale = false,
899 	},
900 };
901 EXPORT_SYMBOL_NS_GPL(st7567_config, "DRM_ST7571");
902 
903 const struct st7571_panel_data st7571_config = {
904 	.init = st7571_lcd_init,
905 	.parse_dt = st7571_parse_dt,
906 	.constraints = {
907 		.min_nlines = 1,
908 		.max_nlines = 128,
909 		.min_ncols = 128,
910 		.max_ncols = 128,
911 		.support_grayscale = true,
912 	},
913 };
914 EXPORT_SYMBOL_NS_GPL(st7571_config, "DRM_ST7571");
915 
916 MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
917 MODULE_DESCRIPTION("DRM Driver for Sitronix ST7571 LCD controller");
918 MODULE_LICENSE("GPL");
919