xref: /openbmc/linux/drivers/gpu/drm/solomon/ssd130x.c (revision cc2f2df4)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * DRM driver for Solomon SSD130x OLED displays
4  *
5  * Copyright 2022 Red Hat Inc.
6  * Author: Javier Martinez Canillas <javierm@redhat.com>
7  *
8  * Based on drivers/video/fbdev/ssd1307fb.c
9  * Copyright 2012 Free Electrons
10  */
11 
12 #include <linux/backlight.h>
13 #include <linux/bitfield.h>
14 #include <linux/bits.h>
15 #include <linux/delay.h>
16 #include <linux/gpio/consumer.h>
17 #include <linux/property.h>
18 #include <linux/pwm.h>
19 #include <linux/regulator/consumer.h>
20 
21 #include <drm/drm_atomic_helper.h>
22 #include <drm/drm_damage_helper.h>
23 #include <drm/drm_fb_cma_helper.h>
24 #include <drm/drm_fb_helper.h>
25 #include <drm/drm_format_helper.h>
26 #include <drm/drm_gem_atomic_helper.h>
27 #include <drm/drm_gem_framebuffer_helper.h>
28 #include <drm/drm_gem_shmem_helper.h>
29 #include <drm/drm_managed.h>
30 #include <drm/drm_modes.h>
31 #include <drm/drm_rect.h>
32 #include <drm/drm_probe_helper.h>
33 
34 #include "ssd130x.h"
35 
36 #define DRIVER_NAME	"ssd130x"
37 #define DRIVER_DESC	"DRM driver for Solomon SSD130x OLED displays"
38 #define DRIVER_DATE	"20220131"
39 #define DRIVER_MAJOR	1
40 #define DRIVER_MINOR	0
41 
42 #define SSD130X_DATA				0x40
43 #define SSD130X_COMMAND				0x80
44 
45 #define SSD130X_SET_ADDRESS_MODE		0x20
46 #define SSD130X_SET_COL_RANGE			0x21
47 #define SSD130X_SET_PAGE_RANGE			0x22
48 #define SSD130X_CONTRAST			0x81
49 #define SSD130X_SET_LOOKUP_TABLE		0x91
50 #define SSD130X_CHARGE_PUMP			0x8d
51 #define SSD130X_SET_SEG_REMAP			0xa0
52 #define SSD130X_DISPLAY_OFF			0xae
53 #define SSD130X_SET_MULTIPLEX_RATIO		0xa8
54 #define SSD130X_DISPLAY_ON			0xaf
55 #define SSD130X_START_PAGE_ADDRESS		0xb0
56 #define SSD130X_SET_COM_SCAN_DIR		0xc0
57 #define SSD130X_SET_DISPLAY_OFFSET		0xd3
58 #define SSD130X_SET_CLOCK_FREQ			0xd5
59 #define SSD130X_SET_AREA_COLOR_MODE		0xd8
60 #define SSD130X_SET_PRECHARGE_PERIOD		0xd9
61 #define SSD130X_SET_COM_PINS_CONFIG		0xda
62 #define SSD130X_SET_VCOMH			0xdb
63 
64 #define SSD130X_SET_SEG_REMAP_MASK		GENMASK(0, 0)
65 #define SSD130X_SET_SEG_REMAP_SET(val)		FIELD_PREP(SSD130X_SET_SEG_REMAP_MASK, (val))
66 #define SSD130X_SET_COM_SCAN_DIR_MASK		GENMASK(3, 3)
67 #define SSD130X_SET_COM_SCAN_DIR_SET(val)	FIELD_PREP(SSD130X_SET_COM_SCAN_DIR_MASK, (val))
68 #define SSD130X_SET_CLOCK_DIV_MASK		GENMASK(3, 0)
69 #define SSD130X_SET_CLOCK_DIV_SET(val)		FIELD_PREP(SSD130X_SET_CLOCK_DIV_MASK, (val))
70 #define SSD130X_SET_CLOCK_FREQ_MASK		GENMASK(7, 4)
71 #define SSD130X_SET_CLOCK_FREQ_SET(val)		FIELD_PREP(SSD130X_SET_CLOCK_FREQ_MASK, (val))
72 #define SSD130X_SET_PRECHARGE_PERIOD1_MASK	GENMASK(3, 0)
73 #define SSD130X_SET_PRECHARGE_PERIOD1_SET(val)	FIELD_PREP(SSD130X_SET_PRECHARGE_PERIOD1_MASK, (val))
74 #define SSD130X_SET_PRECHARGE_PERIOD2_MASK	GENMASK(7, 4)
75 #define SSD130X_SET_PRECHARGE_PERIOD2_SET(val)	FIELD_PREP(SSD130X_SET_PRECHARGE_PERIOD2_MASK, (val))
76 #define SSD130X_SET_COM_PINS_CONFIG1_MASK	GENMASK(4, 4)
77 #define SSD130X_SET_COM_PINS_CONFIG1_SET(val)	FIELD_PREP(SSD130X_SET_COM_PINS_CONFIG1_MASK, !(val))
78 #define SSD130X_SET_COM_PINS_CONFIG2_MASK	GENMASK(5, 5)
79 #define SSD130X_SET_COM_PINS_CONFIG2_SET(val)	FIELD_PREP(SSD130X_SET_COM_PINS_CONFIG2_MASK, (val))
80 
81 #define SSD130X_SET_ADDRESS_MODE_HORIZONTAL	0x00
82 #define SSD130X_SET_ADDRESS_MODE_VERTICAL	0x01
83 #define SSD130X_SET_ADDRESS_MODE_PAGE		0x02
84 
85 #define SSD130X_SET_AREA_COLOR_MODE_ENABLE	0x1e
86 #define SSD130X_SET_AREA_COLOR_MODE_LOW_POWER	0x05
87 
88 #define MAX_CONTRAST 255
89 
90 static inline struct ssd130x_device *drm_to_ssd130x(struct drm_device *drm)
91 {
92 	return container_of(drm, struct ssd130x_device, drm);
93 }
94 
95 /*
96  * Helper to write data (SSD130X_DATA) to the device.
97  */
98 static int ssd130x_write_data(struct ssd130x_device *ssd130x, u8 *values, int count)
99 {
100 	return regmap_bulk_write(ssd130x->regmap, SSD130X_DATA, values, count);
101 }
102 
103 /*
104  * Helper to write command (SSD130X_COMMAND). The fist variadic argument
105  * is the command to write and the following are the command options.
106  *
107  * Note that the ssd130x protocol requires each command and option to be
108  * written as a SSD130X_COMMAND device register value. That is why a call
109  * to regmap_write(..., SSD130X_COMMAND, ...) is done for each argument.
110  */
111 static int ssd130x_write_cmd(struct ssd130x_device *ssd130x, int count,
112 			     /* u8 cmd, u8 option, ... */...)
113 {
114 	va_list ap;
115 	u8 value;
116 	int ret;
117 
118 	va_start(ap, count);
119 
120 	do {
121 		value = va_arg(ap, int);
122 		ret = regmap_write(ssd130x->regmap, SSD130X_COMMAND, value);
123 		if (ret)
124 			goto out_end;
125 	} while (--count);
126 
127 out_end:
128 	va_end(ap);
129 
130 	return ret;
131 }
132 
133 static int ssd130x_set_col_range(struct ssd130x_device *ssd130x,
134 				 u8 col_start, u8 cols)
135 {
136 	u8 col_end = col_start + cols - 1;
137 	int ret;
138 
139 	if (col_start == ssd130x->col_start && col_end == ssd130x->col_end)
140 		return 0;
141 
142 	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_COL_RANGE, col_start, col_end);
143 	if (ret < 0)
144 		return ret;
145 
146 	ssd130x->col_start = col_start;
147 	ssd130x->col_end = col_end;
148 	return 0;
149 }
150 
151 static int ssd130x_set_page_range(struct ssd130x_device *ssd130x,
152 				  u8 page_start, u8 pages)
153 {
154 	u8 page_end = page_start + pages - 1;
155 	int ret;
156 
157 	if (page_start == ssd130x->page_start && page_end == ssd130x->page_end)
158 		return 0;
159 
160 	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_PAGE_RANGE, page_start, page_end);
161 	if (ret < 0)
162 		return ret;
163 
164 	ssd130x->page_start = page_start;
165 	ssd130x->page_end = page_end;
166 	return 0;
167 }
168 
169 static int ssd130x_pwm_enable(struct ssd130x_device *ssd130x)
170 {
171 	struct device *dev = ssd130x->dev;
172 	struct pwm_state pwmstate;
173 
174 	ssd130x->pwm = pwm_get(dev, NULL);
175 	if (IS_ERR(ssd130x->pwm)) {
176 		dev_err(dev, "Could not get PWM from firmware description!\n");
177 		return PTR_ERR(ssd130x->pwm);
178 	}
179 
180 	pwm_init_state(ssd130x->pwm, &pwmstate);
181 	pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
182 	pwm_apply_state(ssd130x->pwm, &pwmstate);
183 
184 	/* Enable the PWM */
185 	pwm_enable(ssd130x->pwm);
186 
187 	dev_dbg(dev, "Using PWM%d with a %lluns period.\n",
188 		ssd130x->pwm->pwm, pwm_get_period(ssd130x->pwm));
189 
190 	return 0;
191 }
192 
193 static void ssd130x_reset(struct ssd130x_device *ssd130x)
194 {
195 	if (!ssd130x->reset)
196 		return;
197 
198 	/* Reset the screen */
199 	gpiod_set_value_cansleep(ssd130x->reset, 1);
200 	udelay(4);
201 	gpiod_set_value_cansleep(ssd130x->reset, 0);
202 	udelay(4);
203 }
204 
205 static int ssd130x_power_on(struct ssd130x_device *ssd130x)
206 {
207 	struct device *dev = ssd130x->dev;
208 	int ret;
209 
210 	ssd130x_reset(ssd130x);
211 
212 	ret = regulator_enable(ssd130x->vcc_reg);
213 	if (ret) {
214 		dev_err(dev, "Failed to enable VCC: %d\n", ret);
215 		return ret;
216 	}
217 
218 	if (ssd130x->device_info->need_pwm) {
219 		ret = ssd130x_pwm_enable(ssd130x);
220 		if (ret) {
221 			dev_err(dev, "Failed to enable PWM: %d\n", ret);
222 			regulator_disable(ssd130x->vcc_reg);
223 			return ret;
224 		}
225 	}
226 
227 	return 0;
228 }
229 
230 static void ssd130x_power_off(struct ssd130x_device *ssd130x)
231 {
232 	pwm_disable(ssd130x->pwm);
233 	pwm_put(ssd130x->pwm);
234 
235 	regulator_disable(ssd130x->vcc_reg);
236 }
237 
238 static int ssd130x_init(struct ssd130x_device *ssd130x)
239 {
240 	u32 precharge, dclk, com_invdir, compins, chargepump, seg_remap;
241 	int ret;
242 
243 	/* Set initial contrast */
244 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CONTRAST, ssd130x->contrast);
245 	if (ret < 0)
246 		return ret;
247 
248 	/* Set segment re-map */
249 	seg_remap = (SSD130X_SET_SEG_REMAP |
250 		     SSD130X_SET_SEG_REMAP_SET(ssd130x->seg_remap));
251 	ret = ssd130x_write_cmd(ssd130x, 1, seg_remap);
252 	if (ret < 0)
253 		return ret;
254 
255 	/* Set COM direction */
256 	com_invdir = (SSD130X_SET_COM_SCAN_DIR |
257 		      SSD130X_SET_COM_SCAN_DIR_SET(ssd130x->com_invdir));
258 	ret = ssd130x_write_cmd(ssd130x,  1, com_invdir);
259 	if (ret < 0)
260 		return ret;
261 
262 	/* Set multiplex ratio value */
263 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
264 	if (ret < 0)
265 		return ret;
266 
267 	/* set display offset value */
268 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_DISPLAY_OFFSET, ssd130x->com_offset);
269 	if (ret < 0)
270 		return ret;
271 
272 	/* Set clock frequency */
273 	dclk = (SSD130X_SET_CLOCK_DIV_SET(ssd130x->dclk_div - 1) |
274 		SSD130X_SET_CLOCK_FREQ_SET(ssd130x->dclk_frq));
275 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_CLOCK_FREQ, dclk);
276 	if (ret < 0)
277 		return ret;
278 
279 	/* Set Area Color Mode ON/OFF & Low Power Display Mode */
280 	if (ssd130x->area_color_enable || ssd130x->low_power) {
281 		u32 mode = 0;
282 
283 		if (ssd130x->area_color_enable)
284 			mode |= SSD130X_SET_AREA_COLOR_MODE_ENABLE;
285 
286 		if (ssd130x->low_power)
287 			mode |= SSD130X_SET_AREA_COLOR_MODE_LOW_POWER;
288 
289 		ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_AREA_COLOR_MODE, mode);
290 		if (ret < 0)
291 			return ret;
292 	}
293 
294 	/* Set precharge period in number of ticks from the internal clock */
295 	precharge = (SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep1) |
296 		     SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep2));
297 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_PRECHARGE_PERIOD, precharge);
298 	if (ret < 0)
299 		return ret;
300 
301 	/* Set COM pins configuration */
302 	compins = BIT(1);
303 	compins |= (SSD130X_SET_COM_PINS_CONFIG1_SET(ssd130x->com_seq) |
304 		    SSD130X_SET_COM_PINS_CONFIG2_SET(ssd130x->com_lrremap));
305 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_COM_PINS_CONFIG, compins);
306 	if (ret < 0)
307 		return ret;
308 
309 	/* Set VCOMH */
310 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_VCOMH, ssd130x->vcomh);
311 	if (ret < 0)
312 		return ret;
313 
314 	/* Turn on the DC-DC Charge Pump */
315 	chargepump = BIT(4);
316 
317 	if (ssd130x->device_info->need_chargepump)
318 		chargepump |= BIT(2);
319 
320 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CHARGE_PUMP, chargepump);
321 	if (ret < 0)
322 		return ret;
323 
324 	/* Set lookup table */
325 	if (ssd130x->lookup_table_set) {
326 		int i;
327 
328 		ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SET_LOOKUP_TABLE);
329 		if (ret < 0)
330 			return ret;
331 
332 		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); i++) {
333 			u8 val = ssd130x->lookup_table[i];
334 
335 			if (val < 31 || val > 63)
336 				dev_warn(ssd130x->dev,
337 					 "lookup table index %d value out of range 31 <= %d <= 63\n",
338 					 i, val);
339 			ret = ssd130x_write_cmd(ssd130x, 1, val);
340 			if (ret < 0)
341 				return ret;
342 		}
343 	}
344 
345 	/* Switch to horizontal addressing mode */
346 	return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
347 				 SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
348 }
349 
350 static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
351 			       struct drm_rect *rect)
352 {
353 	unsigned int x = rect->x1;
354 	unsigned int y = rect->y1;
355 	unsigned int width = drm_rect_width(rect);
356 	unsigned int height = drm_rect_height(rect);
357 	unsigned int line_length = DIV_ROUND_UP(width, 8);
358 	unsigned int pages = DIV_ROUND_UP(height, 8);
359 	struct drm_device *drm = &ssd130x->drm;
360 	u32 array_idx = 0;
361 	int ret, i, j, k;
362 	u8 *data_array = NULL;
363 
364 	drm_WARN_ONCE(drm, y % 8 != 0, "y must be aligned to screen page\n");
365 
366 	data_array = kcalloc(width, pages, GFP_KERNEL);
367 	if (!data_array)
368 		return -ENOMEM;
369 
370 	/*
371 	 * The screen is divided in pages, each having a height of 8
372 	 * pixels, and the width of the screen. When sending a byte of
373 	 * data to the controller, it gives the 8 bits for the current
374 	 * column. I.e, the first byte are the 8 bits of the first
375 	 * column, then the 8 bits for the second column, etc.
376 	 *
377 	 *
378 	 * Representation of the screen, assuming it is 5 bits
379 	 * wide. Each letter-number combination is a bit that controls
380 	 * one pixel.
381 	 *
382 	 * A0 A1 A2 A3 A4
383 	 * B0 B1 B2 B3 B4
384 	 * C0 C1 C2 C3 C4
385 	 * D0 D1 D2 D3 D4
386 	 * E0 E1 E2 E3 E4
387 	 * F0 F1 F2 F3 F4
388 	 * G0 G1 G2 G3 G4
389 	 * H0 H1 H2 H3 H4
390 	 *
391 	 * If you want to update this screen, you need to send 5 bytes:
392 	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
393 	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
394 	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
395 	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
396 	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
397 	 */
398 
399 	ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
400 	if (ret < 0)
401 		goto out_free;
402 
403 	ret = ssd130x_set_page_range(ssd130x, ssd130x->page_offset + y / 8, pages);
404 	if (ret < 0)
405 		goto out_free;
406 
407 	for (i = 0; i < pages; i++) {
408 		int m = 8;
409 
410 		/* Last page may be partial */
411 		if (8 * (y / 8 + i + 1) > ssd130x->height)
412 			m = ssd130x->height % 8;
413 		for (j = 0; j < width; j++) {
414 			u8 data = 0;
415 
416 			for (k = 0; k < m; k++) {
417 				u8 byte = buf[(8 * i + k) * line_length + j / 8];
418 				u8 bit = (byte >> (j % 8)) & 1;
419 
420 				data |= bit << k;
421 			}
422 			data_array[array_idx++] = data;
423 		}
424 	}
425 
426 	ret = ssd130x_write_data(ssd130x, data_array, width * pages);
427 
428 out_free:
429 	kfree(data_array);
430 	return ret;
431 }
432 
433 static void ssd130x_clear_screen(struct ssd130x_device *ssd130x)
434 {
435 	u8 *buf = NULL;
436 	struct drm_rect fullscreen = {
437 		.x1 = 0,
438 		.x2 = ssd130x->width,
439 		.y1 = 0,
440 		.y2 = ssd130x->height,
441 	};
442 
443 	buf = kcalloc(DIV_ROUND_UP(ssd130x->width, 8), ssd130x->height,
444 		      GFP_KERNEL);
445 	if (!buf)
446 		return;
447 
448 	ssd130x_update_rect(ssd130x, buf, &fullscreen);
449 
450 	kfree(buf);
451 }
452 
453 static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf_map *map,
454 				struct drm_rect *rect)
455 {
456 	struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
457 	void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
458 	unsigned int dst_pitch;
459 	int ret = 0;
460 	u8 *buf = NULL;
461 
462 	/* Align y to display page boundaries */
463 	rect->y1 = round_down(rect->y1, 8);
464 	rect->y2 = min_t(unsigned int, round_up(rect->y2, 8), ssd130x->height);
465 
466 	dst_pitch = DIV_ROUND_UP(drm_rect_width(rect), 8);
467 	buf = kcalloc(dst_pitch, drm_rect_height(rect), GFP_KERNEL);
468 	if (!buf)
469 		return -ENOMEM;
470 
471 	drm_fb_xrgb8888_to_mono(buf, dst_pitch, vmap, fb, rect);
472 
473 	ssd130x_update_rect(ssd130x, buf, rect);
474 
475 	kfree(buf);
476 
477 	return ret;
478 }
479 
480 static int ssd130x_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
481 					   const struct drm_display_mode *mode)
482 {
483 	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
484 
485 	if (mode->hdisplay != ssd130x->mode.hdisplay &&
486 	    mode->vdisplay != ssd130x->mode.vdisplay)
487 		return MODE_ONE_SIZE;
488 
489 	if (mode->hdisplay != ssd130x->mode.hdisplay)
490 		return MODE_ONE_WIDTH;
491 
492 	if (mode->vdisplay != ssd130x->mode.vdisplay)
493 		return MODE_ONE_HEIGHT;
494 
495 	return MODE_OK;
496 }
497 
498 static void ssd130x_display_pipe_enable(struct drm_simple_display_pipe *pipe,
499 					struct drm_crtc_state *crtc_state,
500 					struct drm_plane_state *plane_state)
501 {
502 	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
503 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
504 	struct drm_device *drm = &ssd130x->drm;
505 	int idx, ret;
506 
507 	ret = ssd130x_power_on(ssd130x);
508 	if (ret)
509 		return;
510 
511 	ret = ssd130x_init(ssd130x);
512 	if (ret)
513 		goto out_power_off;
514 
515 	if (!drm_dev_enter(drm, &idx))
516 		goto out_power_off;
517 
518 	ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &plane_state->dst);
519 
520 	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON);
521 
522 	backlight_enable(ssd130x->bl_dev);
523 
524 	drm_dev_exit(idx);
525 
526 	return;
527 out_power_off:
528 	ssd130x_power_off(ssd130x);
529 }
530 
531 static void ssd130x_display_pipe_disable(struct drm_simple_display_pipe *pipe)
532 {
533 	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
534 	struct drm_device *drm = &ssd130x->drm;
535 	int idx;
536 
537 	if (!drm_dev_enter(drm, &idx))
538 		return;
539 
540 	ssd130x_clear_screen(ssd130x);
541 
542 	backlight_disable(ssd130x->bl_dev);
543 
544 	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_OFF);
545 
546 	ssd130x_power_off(ssd130x);
547 
548 	drm_dev_exit(idx);
549 }
550 
551 static void ssd130x_display_pipe_update(struct drm_simple_display_pipe *pipe,
552 					struct drm_plane_state *old_plane_state)
553 {
554 	struct ssd130x_device *ssd130x = drm_to_ssd130x(pipe->crtc.dev);
555 	struct drm_plane_state *plane_state = pipe->plane.state;
556 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
557 	struct drm_framebuffer *fb = plane_state->fb;
558 	struct drm_device *drm = &ssd130x->drm;
559 	struct drm_rect src_clip, dst_clip;
560 	int idx;
561 
562 	if (!fb)
563 		return;
564 
565 	if (!pipe->crtc.state->active)
566 		return;
567 
568 	if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip))
569 		return;
570 
571 	dst_clip = plane_state->dst;
572 	if (!drm_rect_intersect(&dst_clip, &src_clip))
573 		return;
574 
575 	if (!drm_dev_enter(drm, &idx))
576 		return;
577 
578 	ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);
579 
580 	drm_dev_exit(idx);
581 }
582 
583 static const struct drm_simple_display_pipe_funcs ssd130x_pipe_funcs = {
584 	.mode_valid = ssd130x_display_pipe_mode_valid,
585 	.enable = ssd130x_display_pipe_enable,
586 	.disable = ssd130x_display_pipe_disable,
587 	.update = ssd130x_display_pipe_update,
588 	DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
589 };
590 
591 static int ssd130x_connector_get_modes(struct drm_connector *connector)
592 {
593 	struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev);
594 	struct drm_display_mode *mode;
595 	struct device *dev = ssd130x->dev;
596 
597 	mode = drm_mode_duplicate(connector->dev, &ssd130x->mode);
598 	if (!mode) {
599 		dev_err(dev, "Failed to duplicated mode\n");
600 		return 0;
601 	}
602 
603 	drm_mode_probed_add(connector, mode);
604 	drm_set_preferred_mode(connector, mode->hdisplay, mode->vdisplay);
605 
606 	/* There is only a single mode */
607 	return 1;
608 }
609 
610 static const struct drm_connector_helper_funcs ssd130x_connector_helper_funcs = {
611 	.get_modes = ssd130x_connector_get_modes,
612 };
613 
614 static const struct drm_connector_funcs ssd130x_connector_funcs = {
615 	.reset = drm_atomic_helper_connector_reset,
616 	.fill_modes = drm_helper_probe_single_connector_modes,
617 	.destroy = drm_connector_cleanup,
618 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
619 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
620 };
621 
622 static const struct drm_mode_config_funcs ssd130x_mode_config_funcs = {
623 	.fb_create = drm_gem_fb_create_with_dirty,
624 	.atomic_check = drm_atomic_helper_check,
625 	.atomic_commit = drm_atomic_helper_commit,
626 };
627 
628 static const uint32_t ssd130x_formats[] = {
629 	DRM_FORMAT_XRGB8888,
630 };
631 
632 DEFINE_DRM_GEM_FOPS(ssd130x_fops);
633 
634 static const struct drm_driver ssd130x_drm_driver = {
635 	DRM_GEM_SHMEM_DRIVER_OPS,
636 	.name			= DRIVER_NAME,
637 	.desc			= DRIVER_DESC,
638 	.date			= DRIVER_DATE,
639 	.major			= DRIVER_MAJOR,
640 	.minor			= DRIVER_MINOR,
641 	.driver_features	= DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
642 	.fops			= &ssd130x_fops,
643 };
644 
645 static int ssd130x_update_bl(struct backlight_device *bdev)
646 {
647 	struct ssd130x_device *ssd130x = bl_get_data(bdev);
648 	int brightness = backlight_get_brightness(bdev);
649 	int ret;
650 
651 	ssd130x->contrast = brightness;
652 
653 	ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_CONTRAST);
654 	if (ret < 0)
655 		return ret;
656 
657 	ret = ssd130x_write_cmd(ssd130x, 1, ssd130x->contrast);
658 	if (ret < 0)
659 		return ret;
660 
661 	return 0;
662 }
663 
664 static const struct backlight_ops ssd130xfb_bl_ops = {
665 	.update_status	= ssd130x_update_bl,
666 };
667 
668 static void ssd130x_parse_properties(struct ssd130x_device *ssd130x)
669 {
670 	struct device *dev = ssd130x->dev;
671 
672 	if (device_property_read_u32(dev, "solomon,width", &ssd130x->width))
673 		ssd130x->width = 96;
674 
675 	if (device_property_read_u32(dev, "solomon,height", &ssd130x->height))
676 		ssd130x->height = 16;
677 
678 	if (device_property_read_u32(dev, "solomon,page-offset", &ssd130x->page_offset))
679 		ssd130x->page_offset = 1;
680 
681 	if (device_property_read_u32(dev, "solomon,col-offset", &ssd130x->col_offset))
682 		ssd130x->col_offset = 0;
683 
684 	if (device_property_read_u32(dev, "solomon,com-offset", &ssd130x->com_offset))
685 		ssd130x->com_offset = 0;
686 
687 	if (device_property_read_u32(dev, "solomon,prechargep1", &ssd130x->prechargep1))
688 		ssd130x->prechargep1 = 2;
689 
690 	if (device_property_read_u32(dev, "solomon,prechargep2", &ssd130x->prechargep2))
691 		ssd130x->prechargep2 = 2;
692 
693 	if (!device_property_read_u8_array(dev, "solomon,lookup-table",
694 					   ssd130x->lookup_table,
695 					   ARRAY_SIZE(ssd130x->lookup_table)))
696 		ssd130x->lookup_table_set = 1;
697 
698 	ssd130x->seg_remap = !device_property_read_bool(dev, "solomon,segment-no-remap");
699 	ssd130x->com_seq = device_property_read_bool(dev, "solomon,com-seq");
700 	ssd130x->com_lrremap = device_property_read_bool(dev, "solomon,com-lrremap");
701 	ssd130x->com_invdir = device_property_read_bool(dev, "solomon,com-invdir");
702 	ssd130x->area_color_enable =
703 		device_property_read_bool(dev, "solomon,area-color-enable");
704 	ssd130x->low_power = device_property_read_bool(dev, "solomon,low-power");
705 
706 	ssd130x->contrast = 127;
707 	ssd130x->vcomh = ssd130x->device_info->default_vcomh;
708 
709 	/* Setup display timing */
710 	if (device_property_read_u32(dev, "solomon,dclk-div", &ssd130x->dclk_div))
711 		ssd130x->dclk_div = ssd130x->device_info->default_dclk_div;
712 	if (device_property_read_u32(dev, "solomon,dclk-frq", &ssd130x->dclk_frq))
713 		ssd130x->dclk_frq = ssd130x->device_info->default_dclk_frq;
714 }
715 
716 static int ssd130x_init_modeset(struct ssd130x_device *ssd130x)
717 {
718 	struct drm_display_mode *mode = &ssd130x->mode;
719 	struct device *dev = ssd130x->dev;
720 	struct drm_device *drm = &ssd130x->drm;
721 	unsigned long max_width, max_height;
722 	int ret;
723 
724 	ret = drmm_mode_config_init(drm);
725 	if (ret) {
726 		dev_err(dev, "DRM mode config init failed: %d\n", ret);
727 		return ret;
728 	}
729 
730 	mode->type = DRM_MODE_TYPE_DRIVER;
731 	mode->clock = 1;
732 	mode->hdisplay = mode->htotal = ssd130x->width;
733 	mode->hsync_start = mode->hsync_end = ssd130x->width;
734 	mode->vdisplay = mode->vtotal = ssd130x->height;
735 	mode->vsync_start = mode->vsync_end = ssd130x->height;
736 	mode->width_mm = 27;
737 	mode->height_mm = 27;
738 
739 	max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH);
740 	max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT);
741 
742 	drm->mode_config.min_width = mode->hdisplay;
743 	drm->mode_config.max_width = max_width;
744 	drm->mode_config.min_height = mode->vdisplay;
745 	drm->mode_config.max_height = max_height;
746 	drm->mode_config.preferred_depth = 32;
747 	drm->mode_config.funcs = &ssd130x_mode_config_funcs;
748 
749 	ret = drm_connector_init(drm, &ssd130x->connector, &ssd130x_connector_funcs,
750 				 DRM_MODE_CONNECTOR_Unknown);
751 	if (ret) {
752 		dev_err(dev, "DRM connector init failed: %d\n", ret);
753 		return ret;
754 	}
755 
756 	drm_connector_helper_add(&ssd130x->connector, &ssd130x_connector_helper_funcs);
757 
758 	ret = drm_simple_display_pipe_init(drm, &ssd130x->pipe, &ssd130x_pipe_funcs,
759 					   ssd130x_formats, ARRAY_SIZE(ssd130x_formats),
760 					   NULL, &ssd130x->connector);
761 	if (ret) {
762 		dev_err(dev, "DRM simple display pipeline init failed: %d\n", ret);
763 		return ret;
764 	}
765 
766 	drm_plane_enable_fb_damage_clips(&ssd130x->pipe.plane);
767 
768 	drm_mode_config_reset(drm);
769 
770 	return 0;
771 }
772 
773 static int ssd130x_get_resources(struct ssd130x_device *ssd130x)
774 {
775 	struct device *dev = ssd130x->dev;
776 
777 	ssd130x->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
778 	if (IS_ERR(ssd130x->reset))
779 		return dev_err_probe(dev, PTR_ERR(ssd130x->reset),
780 				     "Failed to get reset gpio\n");
781 
782 	ssd130x->vcc_reg = devm_regulator_get(dev, "vcc");
783 	if (IS_ERR(ssd130x->vcc_reg))
784 		return dev_err_probe(dev, PTR_ERR(ssd130x->vcc_reg),
785 				     "Failed to get VCC regulator\n");
786 
787 	return 0;
788 }
789 
790 struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
791 {
792 	struct ssd130x_device *ssd130x;
793 	struct backlight_device *bl;
794 	struct drm_device *drm;
795 	int ret;
796 
797 	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
798 				     struct ssd130x_device, drm);
799 	if (IS_ERR(ssd130x))
800 		return ERR_PTR(dev_err_probe(dev, PTR_ERR(ssd130x),
801 					     "Failed to allocate DRM device\n"));
802 
803 	drm = &ssd130x->drm;
804 
805 	ssd130x->dev = dev;
806 	ssd130x->regmap = regmap;
807 	ssd130x->device_info = device_get_match_data(dev);
808 
809 	ssd130x_parse_properties(ssd130x);
810 
811 	ret = ssd130x_get_resources(ssd130x);
812 	if (ret)
813 		return ERR_PTR(ret);
814 
815 	bl = devm_backlight_device_register(dev, dev_name(dev), dev, ssd130x,
816 					    &ssd130xfb_bl_ops, NULL);
817 	if (IS_ERR(bl))
818 		return ERR_PTR(dev_err_probe(dev, PTR_ERR(bl),
819 					     "Unable to register backlight device\n"));
820 
821 	bl->props.brightness = ssd130x->contrast;
822 	bl->props.max_brightness = MAX_CONTRAST;
823 	ssd130x->bl_dev = bl;
824 
825 	ret = ssd130x_init_modeset(ssd130x);
826 	if (ret)
827 		return ERR_PTR(ret);
828 
829 	ret = drm_dev_register(drm, 0);
830 	if (ret)
831 		return ERR_PTR(dev_err_probe(dev, ret, "DRM device register failed\n"));
832 
833 	drm_fbdev_generic_setup(drm, 0);
834 
835 	return ssd130x;
836 }
837 EXPORT_SYMBOL_GPL(ssd130x_probe);
838 
839 int ssd130x_remove(struct ssd130x_device *ssd130x)
840 {
841 	drm_dev_unplug(&ssd130x->drm);
842 
843 	return 0;
844 }
845 EXPORT_SYMBOL_GPL(ssd130x_remove);
846 
847 void ssd130x_shutdown(struct ssd130x_device *ssd130x)
848 {
849 	drm_atomic_helper_shutdown(&ssd130x->drm);
850 }
851 EXPORT_SYMBOL_GPL(ssd130x_shutdown);
852 
853 MODULE_DESCRIPTION(DRIVER_DESC);
854 MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
855 MODULE_LICENSE("GPL v2");
856