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