xref: /openbmc/linux/drivers/gpu/drm/solomon/ssd130x.c (revision f1f288d07afb46517e377deb8d20f187f51b00b2)
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.h>
22 #include <drm/drm_atomic_helper.h>
23 #include <drm/drm_crtc_helper.h>
24 #include <drm/drm_damage_helper.h>
25 #include <drm/drm_edid.h>
26 #include <drm/drm_fbdev_generic.h>
27 #include <drm/drm_format_helper.h>
28 #include <drm/drm_framebuffer.h>
29 #include <drm/drm_gem_atomic_helper.h>
30 #include <drm/drm_gem_framebuffer_helper.h>
31 #include <drm/drm_gem_shmem_helper.h>
32 #include <drm/drm_managed.h>
33 #include <drm/drm_modes.h>
34 #include <drm/drm_rect.h>
35 #include <drm/drm_probe_helper.h>
36 
37 #include "ssd130x.h"
38 
39 #define DRIVER_NAME	"ssd130x"
40 #define DRIVER_DESC	"DRM driver for Solomon SSD130x OLED displays"
41 #define DRIVER_DATE	"20220131"
42 #define DRIVER_MAJOR	1
43 #define DRIVER_MINOR	0
44 
45 #define SSD130X_PAGE_COL_START_LOW		0x00
46 #define SSD130X_PAGE_COL_START_HIGH		0x10
47 #define SSD130X_SET_ADDRESS_MODE		0x20
48 #define SSD130X_SET_COL_RANGE			0x21
49 #define SSD130X_SET_PAGE_RANGE			0x22
50 #define SSD130X_CONTRAST			0x81
51 #define SSD130X_SET_LOOKUP_TABLE		0x91
52 #define SSD130X_CHARGE_PUMP			0x8d
53 #define SSD130X_SET_SEG_REMAP			0xa0
54 #define SSD130X_DISPLAY_OFF			0xae
55 #define SSD130X_SET_MULTIPLEX_RATIO		0xa8
56 #define SSD130X_DISPLAY_ON			0xaf
57 #define SSD130X_START_PAGE_ADDRESS		0xb0
58 #define SSD130X_SET_COM_SCAN_DIR		0xc0
59 #define SSD130X_SET_DISPLAY_OFFSET		0xd3
60 #define SSD130X_SET_CLOCK_FREQ			0xd5
61 #define SSD130X_SET_AREA_COLOR_MODE		0xd8
62 #define SSD130X_SET_PRECHARGE_PERIOD		0xd9
63 #define SSD130X_SET_COM_PINS_CONFIG		0xda
64 #define SSD130X_SET_VCOMH			0xdb
65 
66 #define SSD130X_PAGE_COL_START_MASK		GENMASK(3, 0)
67 #define SSD130X_PAGE_COL_START_HIGH_SET(val)	FIELD_PREP(SSD130X_PAGE_COL_START_MASK, (val) >> 4)
68 #define SSD130X_PAGE_COL_START_LOW_SET(val)	FIELD_PREP(SSD130X_PAGE_COL_START_MASK, (val))
69 #define SSD130X_START_PAGE_ADDRESS_MASK		GENMASK(2, 0)
70 #define SSD130X_START_PAGE_ADDRESS_SET(val)	FIELD_PREP(SSD130X_START_PAGE_ADDRESS_MASK, (val))
71 #define SSD130X_SET_SEG_REMAP_MASK		GENMASK(0, 0)
72 #define SSD130X_SET_SEG_REMAP_SET(val)		FIELD_PREP(SSD130X_SET_SEG_REMAP_MASK, (val))
73 #define SSD130X_SET_COM_SCAN_DIR_MASK		GENMASK(3, 3)
74 #define SSD130X_SET_COM_SCAN_DIR_SET(val)	FIELD_PREP(SSD130X_SET_COM_SCAN_DIR_MASK, (val))
75 #define SSD130X_SET_CLOCK_DIV_MASK		GENMASK(3, 0)
76 #define SSD130X_SET_CLOCK_DIV_SET(val)		FIELD_PREP(SSD130X_SET_CLOCK_DIV_MASK, (val))
77 #define SSD130X_SET_CLOCK_FREQ_MASK		GENMASK(7, 4)
78 #define SSD130X_SET_CLOCK_FREQ_SET(val)		FIELD_PREP(SSD130X_SET_CLOCK_FREQ_MASK, (val))
79 #define SSD130X_SET_PRECHARGE_PERIOD1_MASK	GENMASK(3, 0)
80 #define SSD130X_SET_PRECHARGE_PERIOD1_SET(val)	FIELD_PREP(SSD130X_SET_PRECHARGE_PERIOD1_MASK, (val))
81 #define SSD130X_SET_PRECHARGE_PERIOD2_MASK	GENMASK(7, 4)
82 #define SSD130X_SET_PRECHARGE_PERIOD2_SET(val)	FIELD_PREP(SSD130X_SET_PRECHARGE_PERIOD2_MASK, (val))
83 #define SSD130X_SET_COM_PINS_CONFIG1_MASK	GENMASK(4, 4)
84 #define SSD130X_SET_COM_PINS_CONFIG1_SET(val)	FIELD_PREP(SSD130X_SET_COM_PINS_CONFIG1_MASK, (val))
85 #define SSD130X_SET_COM_PINS_CONFIG2_MASK	GENMASK(5, 5)
86 #define SSD130X_SET_COM_PINS_CONFIG2_SET(val)	FIELD_PREP(SSD130X_SET_COM_PINS_CONFIG2_MASK, (val))
87 
88 #define SSD130X_SET_ADDRESS_MODE_HORIZONTAL	0x00
89 #define SSD130X_SET_ADDRESS_MODE_VERTICAL	0x01
90 #define SSD130X_SET_ADDRESS_MODE_PAGE		0x02
91 
92 #define SSD130X_SET_AREA_COLOR_MODE_ENABLE	0x1e
93 #define SSD130X_SET_AREA_COLOR_MODE_LOW_POWER	0x05
94 
95 #define MAX_CONTRAST 255
96 
97 const struct ssd130x_deviceinfo ssd130x_variants[] = {
98 	[SH1106_ID] = {
99 		.default_vcomh = 0x40,
100 		.default_dclk_div = 1,
101 		.default_dclk_frq = 5,
102 		.default_width = 132,
103 		.default_height = 64,
104 		.page_mode_only = 1,
105 	},
106 	[SSD1305_ID] = {
107 		.default_vcomh = 0x34,
108 		.default_dclk_div = 1,
109 		.default_dclk_frq = 7,
110 		.default_width = 132,
111 		.default_height = 64,
112 	},
113 	[SSD1306_ID] = {
114 		.default_vcomh = 0x20,
115 		.default_dclk_div = 1,
116 		.default_dclk_frq = 8,
117 		.need_chargepump = 1,
118 		.default_width = 128,
119 		.default_height = 64,
120 	},
121 	[SSD1307_ID] = {
122 		.default_vcomh = 0x20,
123 		.default_dclk_div = 2,
124 		.default_dclk_frq = 12,
125 		.need_pwm = 1,
126 		.default_width = 128,
127 		.default_height = 39,
128 	},
129 	[SSD1309_ID] = {
130 		.default_vcomh = 0x34,
131 		.default_dclk_div = 1,
132 		.default_dclk_frq = 10,
133 		.default_width = 128,
134 		.default_height = 64,
135 	}
136 };
137 EXPORT_SYMBOL_NS_GPL(ssd130x_variants, DRM_SSD130X);
138 
139 static inline struct ssd130x_device *drm_to_ssd130x(struct drm_device *drm)
140 {
141 	return container_of(drm, struct ssd130x_device, drm);
142 }
143 
144 /*
145  * Helper to write data (SSD130X_DATA) to the device.
146  */
147 static int ssd130x_write_data(struct ssd130x_device *ssd130x, u8 *values, int count)
148 {
149 	return regmap_bulk_write(ssd130x->regmap, SSD130X_DATA, values, count);
150 }
151 
152 /*
153  * Helper to write command (SSD130X_COMMAND). The fist variadic argument
154  * is the command to write and the following are the command options.
155  *
156  * Note that the ssd130x protocol requires each command and option to be
157  * written as a SSD130X_COMMAND device register value. That is why a call
158  * to regmap_write(..., SSD130X_COMMAND, ...) is done for each argument.
159  */
160 static int ssd130x_write_cmd(struct ssd130x_device *ssd130x, int count,
161 			     /* u8 cmd, u8 option, ... */...)
162 {
163 	va_list ap;
164 	u8 value;
165 	int ret;
166 
167 	va_start(ap, count);
168 
169 	do {
170 		value = va_arg(ap, int);
171 		ret = regmap_write(ssd130x->regmap, SSD130X_COMMAND, value);
172 		if (ret)
173 			goto out_end;
174 	} while (--count);
175 
176 out_end:
177 	va_end(ap);
178 
179 	return ret;
180 }
181 
182 /* Set address range for horizontal/vertical addressing modes */
183 static int ssd130x_set_col_range(struct ssd130x_device *ssd130x,
184 				 u8 col_start, u8 cols)
185 {
186 	u8 col_end = col_start + cols - 1;
187 	int ret;
188 
189 	if (col_start == ssd130x->col_start && col_end == ssd130x->col_end)
190 		return 0;
191 
192 	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_COL_RANGE, col_start, col_end);
193 	if (ret < 0)
194 		return ret;
195 
196 	ssd130x->col_start = col_start;
197 	ssd130x->col_end = col_end;
198 	return 0;
199 }
200 
201 static int ssd130x_set_page_range(struct ssd130x_device *ssd130x,
202 				  u8 page_start, u8 pages)
203 {
204 	u8 page_end = page_start + pages - 1;
205 	int ret;
206 
207 	if (page_start == ssd130x->page_start && page_end == ssd130x->page_end)
208 		return 0;
209 
210 	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_PAGE_RANGE, page_start, page_end);
211 	if (ret < 0)
212 		return ret;
213 
214 	ssd130x->page_start = page_start;
215 	ssd130x->page_end = page_end;
216 	return 0;
217 }
218 
219 /* Set page and column start address for page addressing mode */
220 static int ssd130x_set_page_pos(struct ssd130x_device *ssd130x,
221 				u8 page_start, u8 col_start)
222 {
223 	int ret;
224 	u32 page, col_low, col_high;
225 
226 	page = SSD130X_START_PAGE_ADDRESS |
227 	       SSD130X_START_PAGE_ADDRESS_SET(page_start);
228 	col_low = SSD130X_PAGE_COL_START_LOW |
229 		  SSD130X_PAGE_COL_START_LOW_SET(col_start);
230 	col_high = SSD130X_PAGE_COL_START_HIGH |
231 		   SSD130X_PAGE_COL_START_HIGH_SET(col_start);
232 	ret = ssd130x_write_cmd(ssd130x, 3, page, col_low, col_high);
233 	if (ret < 0)
234 		return ret;
235 
236 	return 0;
237 }
238 
239 static int ssd130x_pwm_enable(struct ssd130x_device *ssd130x)
240 {
241 	struct device *dev = ssd130x->dev;
242 	struct pwm_state pwmstate;
243 
244 	ssd130x->pwm = pwm_get(dev, NULL);
245 	if (IS_ERR(ssd130x->pwm)) {
246 		dev_err(dev, "Could not get PWM from firmware description!\n");
247 		return PTR_ERR(ssd130x->pwm);
248 	}
249 
250 	pwm_init_state(ssd130x->pwm, &pwmstate);
251 	pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
252 	pwm_apply_state(ssd130x->pwm, &pwmstate);
253 
254 	/* Enable the PWM */
255 	pwm_enable(ssd130x->pwm);
256 
257 	dev_dbg(dev, "Using PWM%d with a %lluns period.\n",
258 		ssd130x->pwm->pwm, pwm_get_period(ssd130x->pwm));
259 
260 	return 0;
261 }
262 
263 static void ssd130x_reset(struct ssd130x_device *ssd130x)
264 {
265 	if (!ssd130x->reset)
266 		return;
267 
268 	/* Reset the screen */
269 	gpiod_set_value_cansleep(ssd130x->reset, 1);
270 	udelay(4);
271 	gpiod_set_value_cansleep(ssd130x->reset, 0);
272 	udelay(4);
273 }
274 
275 static int ssd130x_power_on(struct ssd130x_device *ssd130x)
276 {
277 	struct device *dev = ssd130x->dev;
278 	int ret;
279 
280 	ssd130x_reset(ssd130x);
281 
282 	ret = regulator_enable(ssd130x->vcc_reg);
283 	if (ret) {
284 		dev_err(dev, "Failed to enable VCC: %d\n", ret);
285 		return ret;
286 	}
287 
288 	if (ssd130x->device_info->need_pwm) {
289 		ret = ssd130x_pwm_enable(ssd130x);
290 		if (ret) {
291 			dev_err(dev, "Failed to enable PWM: %d\n", ret);
292 			regulator_disable(ssd130x->vcc_reg);
293 			return ret;
294 		}
295 	}
296 
297 	return 0;
298 }
299 
300 static void ssd130x_power_off(struct ssd130x_device *ssd130x)
301 {
302 	pwm_disable(ssd130x->pwm);
303 	pwm_put(ssd130x->pwm);
304 
305 	regulator_disable(ssd130x->vcc_reg);
306 }
307 
308 static int ssd130x_init(struct ssd130x_device *ssd130x)
309 {
310 	u32 precharge, dclk, com_invdir, compins, chargepump, seg_remap;
311 	bool scan_mode;
312 	int ret;
313 
314 	/* Set initial contrast */
315 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CONTRAST, ssd130x->contrast);
316 	if (ret < 0)
317 		return ret;
318 
319 	/* Set segment re-map */
320 	seg_remap = (SSD130X_SET_SEG_REMAP |
321 		     SSD130X_SET_SEG_REMAP_SET(ssd130x->seg_remap));
322 	ret = ssd130x_write_cmd(ssd130x, 1, seg_remap);
323 	if (ret < 0)
324 		return ret;
325 
326 	/* Set COM direction */
327 	com_invdir = (SSD130X_SET_COM_SCAN_DIR |
328 		      SSD130X_SET_COM_SCAN_DIR_SET(ssd130x->com_invdir));
329 	ret = ssd130x_write_cmd(ssd130x,  1, com_invdir);
330 	if (ret < 0)
331 		return ret;
332 
333 	/* Set multiplex ratio value */
334 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
335 	if (ret < 0)
336 		return ret;
337 
338 	/* set display offset value */
339 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_DISPLAY_OFFSET, ssd130x->com_offset);
340 	if (ret < 0)
341 		return ret;
342 
343 	/* Set clock frequency */
344 	dclk = (SSD130X_SET_CLOCK_DIV_SET(ssd130x->dclk_div - 1) |
345 		SSD130X_SET_CLOCK_FREQ_SET(ssd130x->dclk_frq));
346 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_CLOCK_FREQ, dclk);
347 	if (ret < 0)
348 		return ret;
349 
350 	/* Set Area Color Mode ON/OFF & Low Power Display Mode */
351 	if (ssd130x->area_color_enable || ssd130x->low_power) {
352 		u32 mode = 0;
353 
354 		if (ssd130x->area_color_enable)
355 			mode |= SSD130X_SET_AREA_COLOR_MODE_ENABLE;
356 
357 		if (ssd130x->low_power)
358 			mode |= SSD130X_SET_AREA_COLOR_MODE_LOW_POWER;
359 
360 		ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_AREA_COLOR_MODE, mode);
361 		if (ret < 0)
362 			return ret;
363 	}
364 
365 	/* Set precharge period in number of ticks from the internal clock */
366 	precharge = (SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep1) |
367 		     SSD130X_SET_PRECHARGE_PERIOD2_SET(ssd130x->prechargep2));
368 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_PRECHARGE_PERIOD, precharge);
369 	if (ret < 0)
370 		return ret;
371 
372 	/* Set COM pins configuration */
373 	compins = BIT(1);
374 	/*
375 	 * The COM scan mode field values are the inverse of the boolean DT
376 	 * property "solomon,com-seq". The value 0b means scan from COM0 to
377 	 * COM[N - 1] while 1b means scan from COM[N - 1] to COM0.
378 	 */
379 	scan_mode = !ssd130x->com_seq;
380 	compins |= (SSD130X_SET_COM_PINS_CONFIG1_SET(scan_mode) |
381 		    SSD130X_SET_COM_PINS_CONFIG2_SET(ssd130x->com_lrremap));
382 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_COM_PINS_CONFIG, compins);
383 	if (ret < 0)
384 		return ret;
385 
386 	/* Set VCOMH */
387 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_VCOMH, ssd130x->vcomh);
388 	if (ret < 0)
389 		return ret;
390 
391 	/* Turn on the DC-DC Charge Pump */
392 	chargepump = BIT(4);
393 
394 	if (ssd130x->device_info->need_chargepump)
395 		chargepump |= BIT(2);
396 
397 	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CHARGE_PUMP, chargepump);
398 	if (ret < 0)
399 		return ret;
400 
401 	/* Set lookup table */
402 	if (ssd130x->lookup_table_set) {
403 		int i;
404 
405 		ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SET_LOOKUP_TABLE);
406 		if (ret < 0)
407 			return ret;
408 
409 		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); i++) {
410 			u8 val = ssd130x->lookup_table[i];
411 
412 			if (val < 31 || val > 63)
413 				dev_warn(ssd130x->dev,
414 					 "lookup table index %d value out of range 31 <= %d <= 63\n",
415 					 i, val);
416 			ret = ssd130x_write_cmd(ssd130x, 1, val);
417 			if (ret < 0)
418 				return ret;
419 		}
420 	}
421 
422 	/* Switch to page addressing mode */
423 	if (ssd130x->page_address_mode)
424 		return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
425 					 SSD130X_SET_ADDRESS_MODE_PAGE);
426 
427 	/* Switch to horizontal addressing mode */
428 	return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
429 				 SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
430 }
431 
432 static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
433 			       struct drm_rect *rect)
434 {
435 	unsigned int x = rect->x1;
436 	unsigned int y = rect->y1;
437 	unsigned int width = drm_rect_width(rect);
438 	unsigned int height = drm_rect_height(rect);
439 	unsigned int line_length = DIV_ROUND_UP(width, 8);
440 	unsigned int pages = DIV_ROUND_UP(height, 8);
441 	struct drm_device *drm = &ssd130x->drm;
442 	u32 array_idx = 0;
443 	int ret, i, j, k;
444 	u8 *data_array = NULL;
445 
446 	drm_WARN_ONCE(drm, y % 8 != 0, "y must be aligned to screen page\n");
447 
448 	data_array = kcalloc(width, pages, GFP_KERNEL);
449 	if (!data_array)
450 		return -ENOMEM;
451 
452 	/*
453 	 * The screen is divided in pages, each having a height of 8
454 	 * pixels, and the width of the screen. When sending a byte of
455 	 * data to the controller, it gives the 8 bits for the current
456 	 * column. I.e, the first byte are the 8 bits of the first
457 	 * column, then the 8 bits for the second column, etc.
458 	 *
459 	 *
460 	 * Representation of the screen, assuming it is 5 bits
461 	 * wide. Each letter-number combination is a bit that controls
462 	 * one pixel.
463 	 *
464 	 * A0 A1 A2 A3 A4
465 	 * B0 B1 B2 B3 B4
466 	 * C0 C1 C2 C3 C4
467 	 * D0 D1 D2 D3 D4
468 	 * E0 E1 E2 E3 E4
469 	 * F0 F1 F2 F3 F4
470 	 * G0 G1 G2 G3 G4
471 	 * H0 H1 H2 H3 H4
472 	 *
473 	 * If you want to update this screen, you need to send 5 bytes:
474 	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
475 	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
476 	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
477 	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
478 	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
479 	 */
480 
481 	if (!ssd130x->page_address_mode) {
482 		/* Set address range for horizontal addressing mode */
483 		ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
484 		if (ret < 0)
485 			goto out_free;
486 
487 		ret = ssd130x_set_page_range(ssd130x, ssd130x->page_offset + y / 8, pages);
488 		if (ret < 0)
489 			goto out_free;
490 	}
491 
492 	for (i = 0; i < pages; i++) {
493 		int m = 8;
494 
495 		/* Last page may be partial */
496 		if (8 * (y / 8 + i + 1) > ssd130x->height)
497 			m = ssd130x->height % 8;
498 		for (j = 0; j < width; j++) {
499 			u8 data = 0;
500 
501 			for (k = 0; k < m; k++) {
502 				u8 byte = buf[(8 * i + k) * line_length + j / 8];
503 				u8 bit = (byte >> (j % 8)) & 1;
504 
505 				data |= bit << k;
506 			}
507 			data_array[array_idx++] = data;
508 		}
509 
510 		/*
511 		 * In page addressing mode, the start address needs to be reset,
512 		 * and each page then needs to be written out separately.
513 		 */
514 		if (ssd130x->page_address_mode) {
515 			ret = ssd130x_set_page_pos(ssd130x,
516 						   ssd130x->page_offset + i,
517 						   ssd130x->col_offset + x);
518 			if (ret < 0)
519 				goto out_free;
520 
521 			ret = ssd130x_write_data(ssd130x, data_array, width);
522 			if (ret < 0)
523 				goto out_free;
524 
525 			array_idx = 0;
526 		}
527 	}
528 
529 	/* Write out update in one go if we aren't using page addressing mode */
530 	if (!ssd130x->page_address_mode)
531 		ret = ssd130x_write_data(ssd130x, data_array, width * pages);
532 
533 out_free:
534 	kfree(data_array);
535 	return ret;
536 }
537 
538 static void ssd130x_clear_screen(struct ssd130x_device *ssd130x)
539 {
540 	u8 *buf = NULL;
541 	struct drm_rect fullscreen = {
542 		.x1 = 0,
543 		.x2 = ssd130x->width,
544 		.y1 = 0,
545 		.y2 = ssd130x->height,
546 	};
547 
548 	buf = kcalloc(DIV_ROUND_UP(ssd130x->width, 8), ssd130x->height,
549 		      GFP_KERNEL);
550 	if (!buf)
551 		return;
552 
553 	ssd130x_update_rect(ssd130x, buf, &fullscreen);
554 
555 	kfree(buf);
556 }
557 
558 static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *vmap,
559 				struct drm_rect *rect)
560 {
561 	struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
562 	struct iosys_map dst;
563 	unsigned int dst_pitch;
564 	int ret = 0;
565 	u8 *buf = NULL;
566 
567 	/* Align y to display page boundaries */
568 	rect->y1 = round_down(rect->y1, 8);
569 	rect->y2 = min_t(unsigned int, round_up(rect->y2, 8), ssd130x->height);
570 
571 	dst_pitch = DIV_ROUND_UP(drm_rect_width(rect), 8);
572 	buf = kcalloc(dst_pitch, drm_rect_height(rect), GFP_KERNEL);
573 	if (!buf)
574 		return -ENOMEM;
575 
576 	ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
577 	if (ret)
578 		goto out_free;
579 
580 	iosys_map_set_vaddr(&dst, buf);
581 	drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect);
582 
583 	drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
584 
585 	ssd130x_update_rect(ssd130x, buf, rect);
586 
587 out_free:
588 	kfree(buf);
589 
590 	return ret;
591 }
592 
593 static void ssd130x_primary_plane_helper_atomic_update(struct drm_plane *plane,
594 						       struct drm_atomic_state *state)
595 {
596 	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
597 	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
598 	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
599 	struct drm_atomic_helper_damage_iter iter;
600 	struct drm_device *drm = plane->dev;
601 	struct drm_rect dst_clip;
602 	struct drm_rect damage;
603 	int idx;
604 
605 	if (!drm_dev_enter(drm, &idx))
606 		return;
607 
608 	drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
609 	drm_atomic_for_each_plane_damage(&iter, &damage) {
610 		dst_clip = plane_state->dst;
611 
612 		if (!drm_rect_intersect(&dst_clip, &damage))
613 			continue;
614 
615 		ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);
616 	}
617 
618 	drm_dev_exit(idx);
619 }
620 
621 static void ssd130x_primary_plane_helper_atomic_disable(struct drm_plane *plane,
622 							struct drm_atomic_state *state)
623 {
624 	struct drm_device *drm = plane->dev;
625 	struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
626 	int idx;
627 
628 	if (!drm_dev_enter(drm, &idx))
629 		return;
630 
631 	ssd130x_clear_screen(ssd130x);
632 
633 	drm_dev_exit(idx);
634 }
635 
636 static const struct drm_plane_helper_funcs ssd130x_primary_plane_helper_funcs = {
637 	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
638 	.atomic_check = drm_plane_helper_atomic_check,
639 	.atomic_update = ssd130x_primary_plane_helper_atomic_update,
640 	.atomic_disable = ssd130x_primary_plane_helper_atomic_disable,
641 };
642 
643 static const struct drm_plane_funcs ssd130x_primary_plane_funcs = {
644 	.update_plane = drm_atomic_helper_update_plane,
645 	.disable_plane = drm_atomic_helper_disable_plane,
646 	.destroy = drm_plane_cleanup,
647 	DRM_GEM_SHADOW_PLANE_FUNCS,
648 };
649 
650 static enum drm_mode_status ssd130x_crtc_helper_mode_valid(struct drm_crtc *crtc,
651 							   const struct drm_display_mode *mode)
652 {
653 	struct ssd130x_device *ssd130x = drm_to_ssd130x(crtc->dev);
654 
655 	if (mode->hdisplay != ssd130x->mode.hdisplay &&
656 	    mode->vdisplay != ssd130x->mode.vdisplay)
657 		return MODE_ONE_SIZE;
658 	else if (mode->hdisplay != ssd130x->mode.hdisplay)
659 		return MODE_ONE_WIDTH;
660 	else if (mode->vdisplay != ssd130x->mode.vdisplay)
661 		return MODE_ONE_HEIGHT;
662 
663 	return MODE_OK;
664 }
665 
666 /*
667  * The CRTC is always enabled. Screen updates are performed by
668  * the primary plane's atomic_update function. Disabling clears
669  * the screen in the primary plane's atomic_disable function.
670  */
671 static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = {
672 	.mode_valid = ssd130x_crtc_helper_mode_valid,
673 	.atomic_check = drm_crtc_helper_atomic_check,
674 };
675 
676 static const struct drm_crtc_funcs ssd130x_crtc_funcs = {
677 	.reset = drm_atomic_helper_crtc_reset,
678 	.destroy = drm_crtc_cleanup,
679 	.set_config = drm_atomic_helper_set_config,
680 	.page_flip = drm_atomic_helper_page_flip,
681 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
682 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
683 };
684 
685 static void ssd130x_encoder_helper_atomic_enable(struct drm_encoder *encoder,
686 						 struct drm_atomic_state *state)
687 {
688 	struct drm_device *drm = encoder->dev;
689 	struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
690 	int ret;
691 
692 	ret = ssd130x_power_on(ssd130x);
693 	if (ret)
694 		return;
695 
696 	ret = ssd130x_init(ssd130x);
697 	if (ret) {
698 		ssd130x_power_off(ssd130x);
699 		return;
700 	}
701 
702 	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON);
703 
704 	backlight_enable(ssd130x->bl_dev);
705 }
706 
707 static void ssd130x_encoder_helper_atomic_disable(struct drm_encoder *encoder,
708 						  struct drm_atomic_state *state)
709 {
710 	struct drm_device *drm = encoder->dev;
711 	struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
712 
713 	backlight_disable(ssd130x->bl_dev);
714 
715 	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_OFF);
716 
717 	ssd130x_power_off(ssd130x);
718 }
719 
720 static const struct drm_encoder_helper_funcs ssd130x_encoder_helper_funcs = {
721 	.atomic_enable = ssd130x_encoder_helper_atomic_enable,
722 	.atomic_disable = ssd130x_encoder_helper_atomic_disable,
723 };
724 
725 static const struct drm_encoder_funcs ssd130x_encoder_funcs = {
726 	.destroy = drm_encoder_cleanup,
727 };
728 
729 static int ssd130x_connector_helper_get_modes(struct drm_connector *connector)
730 {
731 	struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev);
732 	struct drm_display_mode *mode;
733 	struct device *dev = ssd130x->dev;
734 
735 	mode = drm_mode_duplicate(connector->dev, &ssd130x->mode);
736 	if (!mode) {
737 		dev_err(dev, "Failed to duplicated mode\n");
738 		return 0;
739 	}
740 
741 	drm_mode_probed_add(connector, mode);
742 	drm_set_preferred_mode(connector, mode->hdisplay, mode->vdisplay);
743 
744 	/* There is only a single mode */
745 	return 1;
746 }
747 
748 static const struct drm_connector_helper_funcs ssd130x_connector_helper_funcs = {
749 	.get_modes = ssd130x_connector_helper_get_modes,
750 };
751 
752 static const struct drm_connector_funcs ssd130x_connector_funcs = {
753 	.reset = drm_atomic_helper_connector_reset,
754 	.fill_modes = drm_helper_probe_single_connector_modes,
755 	.destroy = drm_connector_cleanup,
756 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
757 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
758 };
759 
760 static const struct drm_mode_config_funcs ssd130x_mode_config_funcs = {
761 	.fb_create = drm_gem_fb_create_with_dirty,
762 	.atomic_check = drm_atomic_helper_check,
763 	.atomic_commit = drm_atomic_helper_commit,
764 };
765 
766 static const uint32_t ssd130x_formats[] = {
767 	DRM_FORMAT_XRGB8888,
768 };
769 
770 DEFINE_DRM_GEM_FOPS(ssd130x_fops);
771 
772 static const struct drm_driver ssd130x_drm_driver = {
773 	DRM_GEM_SHMEM_DRIVER_OPS,
774 	.name			= DRIVER_NAME,
775 	.desc			= DRIVER_DESC,
776 	.date			= DRIVER_DATE,
777 	.major			= DRIVER_MAJOR,
778 	.minor			= DRIVER_MINOR,
779 	.driver_features	= DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
780 	.fops			= &ssd130x_fops,
781 };
782 
783 static int ssd130x_update_bl(struct backlight_device *bdev)
784 {
785 	struct ssd130x_device *ssd130x = bl_get_data(bdev);
786 	int brightness = backlight_get_brightness(bdev);
787 	int ret;
788 
789 	ssd130x->contrast = brightness;
790 
791 	ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_CONTRAST);
792 	if (ret < 0)
793 		return ret;
794 
795 	ret = ssd130x_write_cmd(ssd130x, 1, ssd130x->contrast);
796 	if (ret < 0)
797 		return ret;
798 
799 	return 0;
800 }
801 
802 static const struct backlight_ops ssd130xfb_bl_ops = {
803 	.update_status	= ssd130x_update_bl,
804 };
805 
806 static void ssd130x_parse_properties(struct ssd130x_device *ssd130x)
807 {
808 	struct device *dev = ssd130x->dev;
809 
810 	if (device_property_read_u32(dev, "solomon,width", &ssd130x->width))
811 		ssd130x->width = ssd130x->device_info->default_width;
812 
813 	if (device_property_read_u32(dev, "solomon,height", &ssd130x->height))
814 		ssd130x->height = ssd130x->device_info->default_height;
815 
816 	if (device_property_read_u32(dev, "solomon,page-offset", &ssd130x->page_offset))
817 		ssd130x->page_offset = 1;
818 
819 	if (device_property_read_u32(dev, "solomon,col-offset", &ssd130x->col_offset))
820 		ssd130x->col_offset = 0;
821 
822 	if (device_property_read_u32(dev, "solomon,com-offset", &ssd130x->com_offset))
823 		ssd130x->com_offset = 0;
824 
825 	if (device_property_read_u32(dev, "solomon,prechargep1", &ssd130x->prechargep1))
826 		ssd130x->prechargep1 = 2;
827 
828 	if (device_property_read_u32(dev, "solomon,prechargep2", &ssd130x->prechargep2))
829 		ssd130x->prechargep2 = 2;
830 
831 	if (!device_property_read_u8_array(dev, "solomon,lookup-table",
832 					   ssd130x->lookup_table,
833 					   ARRAY_SIZE(ssd130x->lookup_table)))
834 		ssd130x->lookup_table_set = 1;
835 
836 	ssd130x->seg_remap = !device_property_read_bool(dev, "solomon,segment-no-remap");
837 	ssd130x->com_seq = device_property_read_bool(dev, "solomon,com-seq");
838 	ssd130x->com_lrremap = device_property_read_bool(dev, "solomon,com-lrremap");
839 	ssd130x->com_invdir = device_property_read_bool(dev, "solomon,com-invdir");
840 	ssd130x->area_color_enable =
841 		device_property_read_bool(dev, "solomon,area-color-enable");
842 	ssd130x->low_power = device_property_read_bool(dev, "solomon,low-power");
843 
844 	ssd130x->contrast = 127;
845 	ssd130x->vcomh = ssd130x->device_info->default_vcomh;
846 
847 	/* Setup display timing */
848 	if (device_property_read_u32(dev, "solomon,dclk-div", &ssd130x->dclk_div))
849 		ssd130x->dclk_div = ssd130x->device_info->default_dclk_div;
850 	if (device_property_read_u32(dev, "solomon,dclk-frq", &ssd130x->dclk_frq))
851 		ssd130x->dclk_frq = ssd130x->device_info->default_dclk_frq;
852 }
853 
854 static int ssd130x_init_modeset(struct ssd130x_device *ssd130x)
855 {
856 	struct drm_display_mode *mode = &ssd130x->mode;
857 	struct device *dev = ssd130x->dev;
858 	struct drm_device *drm = &ssd130x->drm;
859 	unsigned long max_width, max_height;
860 	struct drm_plane *primary_plane;
861 	struct drm_crtc *crtc;
862 	struct drm_encoder *encoder;
863 	struct drm_connector *connector;
864 	int ret;
865 
866 	/*
867 	 * Modesetting
868 	 */
869 
870 	ret = drmm_mode_config_init(drm);
871 	if (ret) {
872 		dev_err(dev, "DRM mode config init failed: %d\n", ret);
873 		return ret;
874 	}
875 
876 	mode->type = DRM_MODE_TYPE_DRIVER;
877 	mode->clock = 1;
878 	mode->hdisplay = mode->htotal = ssd130x->width;
879 	mode->hsync_start = mode->hsync_end = ssd130x->width;
880 	mode->vdisplay = mode->vtotal = ssd130x->height;
881 	mode->vsync_start = mode->vsync_end = ssd130x->height;
882 	mode->width_mm = 27;
883 	mode->height_mm = 27;
884 
885 	max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH);
886 	max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT);
887 
888 	drm->mode_config.min_width = mode->hdisplay;
889 	drm->mode_config.max_width = max_width;
890 	drm->mode_config.min_height = mode->vdisplay;
891 	drm->mode_config.max_height = max_height;
892 	drm->mode_config.preferred_depth = 24;
893 	drm->mode_config.funcs = &ssd130x_mode_config_funcs;
894 
895 	/* Primary plane */
896 
897 	primary_plane = &ssd130x->primary_plane;
898 	ret = drm_universal_plane_init(drm, primary_plane, 0, &ssd130x_primary_plane_funcs,
899 				       ssd130x_formats, ARRAY_SIZE(ssd130x_formats),
900 				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
901 	if (ret) {
902 		dev_err(dev, "DRM primary plane init failed: %d\n", ret);
903 		return ret;
904 	}
905 
906 	drm_plane_helper_add(primary_plane, &ssd130x_primary_plane_helper_funcs);
907 
908 	drm_plane_enable_fb_damage_clips(primary_plane);
909 
910 	/* CRTC */
911 
912 	crtc = &ssd130x->crtc;
913 	ret = drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
914 					&ssd130x_crtc_funcs, NULL);
915 	if (ret) {
916 		dev_err(dev, "DRM crtc init failed: %d\n", ret);
917 		return ret;
918 	}
919 
920 	drm_crtc_helper_add(crtc, &ssd130x_crtc_helper_funcs);
921 
922 	/* Encoder */
923 
924 	encoder = &ssd130x->encoder;
925 	ret = drm_encoder_init(drm, encoder, &ssd130x_encoder_funcs,
926 			       DRM_MODE_ENCODER_NONE, NULL);
927 	if (ret) {
928 		dev_err(dev, "DRM encoder init failed: %d\n", ret);
929 		return ret;
930 	}
931 
932 	drm_encoder_helper_add(encoder, &ssd130x_encoder_helper_funcs);
933 
934 	encoder->possible_crtcs = drm_crtc_mask(crtc);
935 
936 	/* Connector */
937 
938 	connector = &ssd130x->connector;
939 	ret = drm_connector_init(drm, connector, &ssd130x_connector_funcs,
940 				 DRM_MODE_CONNECTOR_Unknown);
941 	if (ret) {
942 		dev_err(dev, "DRM connector init failed: %d\n", ret);
943 		return ret;
944 	}
945 
946 	drm_connector_helper_add(connector, &ssd130x_connector_helper_funcs);
947 
948 	ret = drm_connector_attach_encoder(connector, encoder);
949 	if (ret) {
950 		dev_err(dev, "DRM attach connector to encoder failed: %d\n", ret);
951 		return ret;
952 	}
953 
954 	drm_mode_config_reset(drm);
955 
956 	return 0;
957 }
958 
959 static int ssd130x_get_resources(struct ssd130x_device *ssd130x)
960 {
961 	struct device *dev = ssd130x->dev;
962 
963 	ssd130x->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
964 	if (IS_ERR(ssd130x->reset))
965 		return dev_err_probe(dev, PTR_ERR(ssd130x->reset),
966 				     "Failed to get reset gpio\n");
967 
968 	ssd130x->vcc_reg = devm_regulator_get(dev, "vcc");
969 	if (IS_ERR(ssd130x->vcc_reg))
970 		return dev_err_probe(dev, PTR_ERR(ssd130x->vcc_reg),
971 				     "Failed to get VCC regulator\n");
972 
973 	return 0;
974 }
975 
976 struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
977 {
978 	struct ssd130x_device *ssd130x;
979 	struct backlight_device *bl;
980 	struct drm_device *drm;
981 	int ret;
982 
983 	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
984 				     struct ssd130x_device, drm);
985 	if (IS_ERR(ssd130x))
986 		return ERR_PTR(dev_err_probe(dev, PTR_ERR(ssd130x),
987 					     "Failed to allocate DRM device\n"));
988 
989 	drm = &ssd130x->drm;
990 
991 	ssd130x->dev = dev;
992 	ssd130x->regmap = regmap;
993 	ssd130x->device_info = device_get_match_data(dev);
994 
995 	if (ssd130x->device_info->page_mode_only)
996 		ssd130x->page_address_mode = 1;
997 
998 	ssd130x_parse_properties(ssd130x);
999 
1000 	ret = ssd130x_get_resources(ssd130x);
1001 	if (ret)
1002 		return ERR_PTR(ret);
1003 
1004 	bl = devm_backlight_device_register(dev, dev_name(dev), dev, ssd130x,
1005 					    &ssd130xfb_bl_ops, NULL);
1006 	if (IS_ERR(bl))
1007 		return ERR_PTR(dev_err_probe(dev, PTR_ERR(bl),
1008 					     "Unable to register backlight device\n"));
1009 
1010 	bl->props.brightness = ssd130x->contrast;
1011 	bl->props.max_brightness = MAX_CONTRAST;
1012 	ssd130x->bl_dev = bl;
1013 
1014 	ret = ssd130x_init_modeset(ssd130x);
1015 	if (ret)
1016 		return ERR_PTR(ret);
1017 
1018 	ret = drm_dev_register(drm, 0);
1019 	if (ret)
1020 		return ERR_PTR(dev_err_probe(dev, ret, "DRM device register failed\n"));
1021 
1022 	drm_fbdev_generic_setup(drm, 32);
1023 
1024 	return ssd130x;
1025 }
1026 EXPORT_SYMBOL_GPL(ssd130x_probe);
1027 
1028 void ssd130x_remove(struct ssd130x_device *ssd130x)
1029 {
1030 	drm_dev_unplug(&ssd130x->drm);
1031 }
1032 EXPORT_SYMBOL_GPL(ssd130x_remove);
1033 
1034 void ssd130x_shutdown(struct ssd130x_device *ssd130x)
1035 {
1036 	drm_atomic_helper_shutdown(&ssd130x->drm);
1037 }
1038 EXPORT_SYMBOL_GPL(ssd130x_shutdown);
1039 
1040 MODULE_DESCRIPTION(DRIVER_DESC);
1041 MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
1042 MODULE_LICENSE("GPL v2");
1043