1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * DRM driver for Solomon SSD13xx 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/clients/drm_client_setup.h>
22 #include <drm/drm_atomic.h>
23 #include <drm/drm_atomic_helper.h>
24 #include <drm/drm_crtc_helper.h>
25 #include <drm/drm_damage_helper.h>
26 #include <drm/drm_edid.h>
27 #include <drm/drm_fbdev_shmem.h>
28 #include <drm/drm_format_helper.h>
29 #include <drm/drm_framebuffer.h>
30 #include <drm/drm_gem_atomic_helper.h>
31 #include <drm/drm_gem_framebuffer_helper.h>
32 #include <drm/drm_gem_shmem_helper.h>
33 #include <drm/drm_managed.h>
34 #include <drm/drm_modes.h>
35 #include <drm/drm_rect.h>
36 #include <drm/drm_print.h>
37 #include <drm/drm_probe_helper.h>
38
39 #include "ssd130x.h"
40
41 #define DRIVER_NAME "ssd130x"
42 #define DRIVER_DESC "DRM driver for Solomon SSD13xx OLED displays"
43 #define DRIVER_MAJOR 1
44 #define DRIVER_MINOR 0
45
46 #define SSD130X_PAGE_HEIGHT 8
47
48 #define SSD132X_SEGMENT_WIDTH 2
49
50 /* ssd13xx commands */
51 #define SSD13XX_CONTRAST 0x81
52 #define SSD13XX_SET_SEG_REMAP 0xa0
53 #define SSD13XX_SET_MULTIPLEX_RATIO 0xa8
54 #define SSD13XX_DISPLAY_OFF 0xae
55 #define SSD13XX_DISPLAY_ON 0xaf
56
57 #define SSD13XX_SET_SEG_REMAP_MASK GENMASK(0, 0)
58 #define SSD13XX_SET_SEG_REMAP_SET(val) FIELD_PREP(SSD13XX_SET_SEG_REMAP_MASK, (val))
59
60 /* ssd130x commands */
61 #define SSD130X_PAGE_COL_START_LOW 0x00
62 #define SSD130X_PAGE_COL_START_HIGH 0x10
63 #define SSD130X_SET_ADDRESS_MODE 0x20
64 #define SSD130X_SET_COL_RANGE 0x21
65 #define SSD130X_SET_PAGE_RANGE 0x22
66 #define SSD130X_SET_LOOKUP_TABLE 0x91
67 #define SSD130X_CHARGE_PUMP 0x8d
68 #define SSD130X_START_PAGE_ADDRESS 0xb0
69 #define SSD130X_SET_COM_SCAN_DIR 0xc0
70 #define SSD130X_SET_DISPLAY_OFFSET 0xd3
71 #define SSD130X_SET_CLOCK_FREQ 0xd5
72 #define SSD130X_SET_AREA_COLOR_MODE 0xd8
73 #define SSD130X_SET_PRECHARGE_PERIOD 0xd9
74 #define SSD130X_SET_COM_PINS_CONFIG 0xda
75 #define SSD130X_SET_VCOMH 0xdb
76
77 /* ssd130x commands accessors */
78 #define SSD130X_PAGE_COL_START_MASK GENMASK(3, 0)
79 #define SSD130X_PAGE_COL_START_HIGH_SET(val) FIELD_PREP(SSD130X_PAGE_COL_START_MASK, (val) >> 4)
80 #define SSD130X_PAGE_COL_START_LOW_SET(val) FIELD_PREP(SSD130X_PAGE_COL_START_MASK, (val))
81 #define SSD130X_START_PAGE_ADDRESS_MASK GENMASK(2, 0)
82 #define SSD130X_START_PAGE_ADDRESS_SET(val) FIELD_PREP(SSD130X_START_PAGE_ADDRESS_MASK, (val))
83 #define SSD130X_SET_COM_SCAN_DIR_MASK GENMASK(3, 3)
84 #define SSD130X_SET_COM_SCAN_DIR_SET(val) FIELD_PREP(SSD130X_SET_COM_SCAN_DIR_MASK, (val))
85 #define SSD130X_SET_CLOCK_DIV_MASK GENMASK(3, 0)
86 #define SSD130X_SET_CLOCK_DIV_SET(val) FIELD_PREP(SSD130X_SET_CLOCK_DIV_MASK, (val))
87 #define SSD130X_SET_CLOCK_FREQ_MASK GENMASK(7, 4)
88 #define SSD130X_SET_CLOCK_FREQ_SET(val) FIELD_PREP(SSD130X_SET_CLOCK_FREQ_MASK, (val))
89 #define SSD130X_SET_PRECHARGE_PERIOD1_MASK GENMASK(3, 0)
90 #define SSD130X_SET_PRECHARGE_PERIOD1_SET(val) FIELD_PREP(SSD130X_SET_PRECHARGE_PERIOD1_MASK, (val))
91 #define SSD130X_SET_PRECHARGE_PERIOD2_MASK GENMASK(7, 4)
92 #define SSD130X_SET_PRECHARGE_PERIOD2_SET(val) FIELD_PREP(SSD130X_SET_PRECHARGE_PERIOD2_MASK, (val))
93 #define SSD130X_SET_COM_PINS_CONFIG1_MASK GENMASK(4, 4)
94 #define SSD130X_SET_COM_PINS_CONFIG1_SET(val) FIELD_PREP(SSD130X_SET_COM_PINS_CONFIG1_MASK, (val))
95 #define SSD130X_SET_COM_PINS_CONFIG2_MASK GENMASK(5, 5)
96 #define SSD130X_SET_COM_PINS_CONFIG2_SET(val) FIELD_PREP(SSD130X_SET_COM_PINS_CONFIG2_MASK, (val))
97
98 #define SSD130X_SET_ADDRESS_MODE_HORIZONTAL 0x00
99 #define SSD130X_SET_ADDRESS_MODE_VERTICAL 0x01
100 #define SSD130X_SET_ADDRESS_MODE_PAGE 0x02
101
102 #define SSD130X_SET_AREA_COLOR_MODE_ENABLE 0x1e
103 #define SSD130X_SET_AREA_COLOR_MODE_LOW_POWER 0x05
104
105 /* ssd132x commands */
106 #define SSD132X_SET_COL_RANGE 0x15
107 #define SSD132X_SET_DEACTIVATE_SCROLL 0x2e
108 #define SSD132X_SET_ROW_RANGE 0x75
109 #define SSD132X_SET_DISPLAY_START 0xa1
110 #define SSD132X_SET_DISPLAY_OFFSET 0xa2
111 #define SSD132X_SET_DISPLAY_NORMAL 0xa4
112 #define SSD132X_SET_FUNCTION_SELECT_A 0xab
113 #define SSD132X_SET_PHASE_LENGTH 0xb1
114 #define SSD132X_SET_CLOCK_FREQ 0xb3
115 #define SSD132X_SET_GPIO 0xb5
116 #define SSD132X_SET_PRECHARGE_PERIOD 0xb6
117 #define SSD132X_SET_GRAY_SCALE_TABLE 0xb8
118 #define SSD132X_SELECT_DEFAULT_TABLE 0xb9
119 #define SSD132X_SET_PRECHARGE_VOLTAGE 0xbc
120 #define SSD130X_SET_VCOMH_VOLTAGE 0xbe
121 #define SSD132X_SET_FUNCTION_SELECT_B 0xd5
122
123 /* ssd133x commands */
124 #define SSD133X_SET_COL_RANGE 0x15
125 #define SSD133X_SET_ROW_RANGE 0x75
126 #define SSD133X_CONTRAST_A 0x81
127 #define SSD133X_CONTRAST_B 0x82
128 #define SSD133X_CONTRAST_C 0x83
129 #define SSD133X_SET_MASTER_CURRENT 0x87
130 #define SSD132X_SET_PRECHARGE_A 0x8a
131 #define SSD132X_SET_PRECHARGE_B 0x8b
132 #define SSD132X_SET_PRECHARGE_C 0x8c
133 #define SSD133X_SET_DISPLAY_START 0xa1
134 #define SSD133X_SET_DISPLAY_OFFSET 0xa2
135 #define SSD133X_SET_DISPLAY_NORMAL 0xa4
136 #define SSD133X_SET_MASTER_CONFIG 0xad
137 #define SSD133X_POWER_SAVE_MODE 0xb0
138 #define SSD133X_PHASES_PERIOD 0xb1
139 #define SSD133X_SET_CLOCK_FREQ 0xb3
140 #define SSD133X_SET_PRECHARGE_VOLTAGE 0xbb
141 #define SSD133X_SET_VCOMH_VOLTAGE 0xbe
142
143 #define MAX_CONTRAST 255
144
145 const struct ssd130x_deviceinfo ssd130x_variants[] = {
146 [SH1106_ID] = {
147 .default_vcomh = 0x40,
148 .default_dclk_div = 1,
149 .default_dclk_frq = 5,
150 .default_width = 132,
151 .default_height = 64,
152 .page_mode_only = 1,
153 .family_id = SSD130X_FAMILY,
154 },
155 [SSD1305_ID] = {
156 .default_vcomh = 0x34,
157 .default_dclk_div = 1,
158 .default_dclk_frq = 7,
159 .default_width = 132,
160 .default_height = 64,
161 .family_id = SSD130X_FAMILY,
162 },
163 [SSD1306_ID] = {
164 .default_vcomh = 0x20,
165 .default_dclk_div = 1,
166 .default_dclk_frq = 8,
167 .need_chargepump = 1,
168 .default_width = 128,
169 .default_height = 64,
170 .family_id = SSD130X_FAMILY,
171 },
172 [SSD1307_ID] = {
173 .default_vcomh = 0x20,
174 .default_dclk_div = 2,
175 .default_dclk_frq = 12,
176 .need_pwm = 1,
177 .default_width = 128,
178 .default_height = 39,
179 .family_id = SSD130X_FAMILY,
180 },
181 [SSD1309_ID] = {
182 .default_vcomh = 0x34,
183 .default_dclk_div = 1,
184 .default_dclk_frq = 10,
185 .default_width = 128,
186 .default_height = 64,
187 .family_id = SSD130X_FAMILY,
188 },
189 /* ssd132x family */
190 [SSD1322_ID] = {
191 .default_width = 480,
192 .default_height = 128,
193 .family_id = SSD132X_FAMILY,
194 },
195 [SSD1325_ID] = {
196 .default_width = 128,
197 .default_height = 80,
198 .family_id = SSD132X_FAMILY,
199 },
200 [SSD1327_ID] = {
201 .default_width = 128,
202 .default_height = 128,
203 .family_id = SSD132X_FAMILY,
204 },
205 /* ssd133x family */
206 [SSD1331_ID] = {
207 .default_width = 96,
208 .default_height = 64,
209 .family_id = SSD133X_FAMILY,
210 }
211 };
212 EXPORT_SYMBOL_NS_GPL(ssd130x_variants, "DRM_SSD130X");
213
214 struct ssd130x_crtc_state {
215 struct drm_crtc_state base;
216 /* Buffer to store pixels in HW format and written to the panel */
217 u8 *data_array;
218 };
219
220 struct ssd130x_plane_state {
221 struct drm_shadow_plane_state base;
222 /* Intermediate buffer to convert pixels from XRGB8888 to HW format */
223 u8 *buffer;
224 };
225
to_ssd130x_crtc_state(struct drm_crtc_state * state)226 static inline struct ssd130x_crtc_state *to_ssd130x_crtc_state(struct drm_crtc_state *state)
227 {
228 return container_of(state, struct ssd130x_crtc_state, base);
229 }
230
to_ssd130x_plane_state(struct drm_plane_state * state)231 static inline struct ssd130x_plane_state *to_ssd130x_plane_state(struct drm_plane_state *state)
232 {
233 return container_of(state, struct ssd130x_plane_state, base.base);
234 }
235
drm_to_ssd130x(struct drm_device * drm)236 static inline struct ssd130x_device *drm_to_ssd130x(struct drm_device *drm)
237 {
238 return container_of(drm, struct ssd130x_device, drm);
239 }
240
241 /*
242 * Helper to write data (SSD13XX_DATA) to the device.
243 */
ssd130x_write_data(struct ssd130x_device * ssd130x,u8 * values,int count)244 static int ssd130x_write_data(struct ssd130x_device *ssd130x, u8 *values, int count)
245 {
246 return regmap_bulk_write(ssd130x->regmap, SSD13XX_DATA, values, count);
247 }
248
249 /*
250 * Helper to write command (SSD13XX_COMMAND). The fist variadic argument
251 * is the command to write and the following are the command options.
252 *
253 * Note that the ssd13xx protocol requires each command and option to be
254 * written as a SSD13XX_COMMAND device register value. That is why a call
255 * to regmap_write(..., SSD13XX_COMMAND, ...) is done for each argument.
256 */
ssd130x_write_cmd(struct ssd130x_device * ssd130x,int count,...)257 static int ssd130x_write_cmd(struct ssd130x_device *ssd130x, int count,
258 /* u8 cmd, u8 option, ... */...)
259 {
260 va_list ap;
261 u8 value;
262 int ret;
263
264 va_start(ap, count);
265
266 do {
267 value = va_arg(ap, int);
268 ret = regmap_write(ssd130x->regmap, SSD13XX_COMMAND, value);
269 if (ret)
270 goto out_end;
271 } while (--count);
272
273 out_end:
274 va_end(ap);
275
276 return ret;
277 }
278
279 /* Set address range for horizontal/vertical addressing modes */
ssd130x_set_col_range(struct ssd130x_device * ssd130x,u8 col_start,u8 cols)280 static int ssd130x_set_col_range(struct ssd130x_device *ssd130x,
281 u8 col_start, u8 cols)
282 {
283 u8 col_end = col_start + cols - 1;
284 int ret;
285
286 if (col_start == ssd130x->col_start && col_end == ssd130x->col_end)
287 return 0;
288
289 ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_COL_RANGE, col_start, col_end);
290 if (ret < 0)
291 return ret;
292
293 ssd130x->col_start = col_start;
294 ssd130x->col_end = col_end;
295 return 0;
296 }
297
ssd130x_set_page_range(struct ssd130x_device * ssd130x,u8 page_start,u8 pages)298 static int ssd130x_set_page_range(struct ssd130x_device *ssd130x,
299 u8 page_start, u8 pages)
300 {
301 u8 page_end = page_start + pages - 1;
302 int ret;
303
304 if (page_start == ssd130x->page_start && page_end == ssd130x->page_end)
305 return 0;
306
307 ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_PAGE_RANGE, page_start, page_end);
308 if (ret < 0)
309 return ret;
310
311 ssd130x->page_start = page_start;
312 ssd130x->page_end = page_end;
313 return 0;
314 }
315
316 /* Set page and column start address for page addressing mode */
ssd130x_set_page_pos(struct ssd130x_device * ssd130x,u8 page_start,u8 col_start)317 static int ssd130x_set_page_pos(struct ssd130x_device *ssd130x,
318 u8 page_start, u8 col_start)
319 {
320 int ret;
321 u32 page, col_low, col_high;
322
323 page = SSD130X_START_PAGE_ADDRESS |
324 SSD130X_START_PAGE_ADDRESS_SET(page_start);
325 col_low = SSD130X_PAGE_COL_START_LOW |
326 SSD130X_PAGE_COL_START_LOW_SET(col_start);
327 col_high = SSD130X_PAGE_COL_START_HIGH |
328 SSD130X_PAGE_COL_START_HIGH_SET(col_start);
329 ret = ssd130x_write_cmd(ssd130x, 3, page, col_low, col_high);
330 if (ret < 0)
331 return ret;
332
333 return 0;
334 }
335
ssd130x_pwm_enable(struct ssd130x_device * ssd130x)336 static int ssd130x_pwm_enable(struct ssd130x_device *ssd130x)
337 {
338 struct device *dev = ssd130x->dev;
339 struct pwm_state pwmstate;
340
341 ssd130x->pwm = pwm_get(dev, NULL);
342 if (IS_ERR(ssd130x->pwm)) {
343 dev_err(dev, "Could not get PWM from firmware description!\n");
344 return PTR_ERR(ssd130x->pwm);
345 }
346
347 pwm_init_state(ssd130x->pwm, &pwmstate);
348 pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
349 pwm_apply_might_sleep(ssd130x->pwm, &pwmstate);
350
351 /* Enable the PWM */
352 pwm_enable(ssd130x->pwm);
353
354 dev_dbg(dev, "Using PWM %s with a %lluns period.\n",
355 ssd130x->pwm->label, pwm_get_period(ssd130x->pwm));
356
357 return 0;
358 }
359
ssd130x_reset(struct ssd130x_device * ssd130x)360 static void ssd130x_reset(struct ssd130x_device *ssd130x)
361 {
362 if (!ssd130x->reset)
363 return;
364
365 /* Reset the screen */
366 gpiod_set_value_cansleep(ssd130x->reset, 1);
367 udelay(4);
368 gpiod_set_value_cansleep(ssd130x->reset, 0);
369 udelay(4);
370 }
371
ssd130x_power_on(struct ssd130x_device * ssd130x)372 static int ssd130x_power_on(struct ssd130x_device *ssd130x)
373 {
374 struct device *dev = ssd130x->dev;
375 int ret;
376
377 ssd130x_reset(ssd130x);
378
379 ret = regulator_enable(ssd130x->vcc_reg);
380 if (ret) {
381 dev_err(dev, "Failed to enable VCC: %d\n", ret);
382 return ret;
383 }
384
385 if (ssd130x->device_info->need_pwm) {
386 ret = ssd130x_pwm_enable(ssd130x);
387 if (ret) {
388 dev_err(dev, "Failed to enable PWM: %d\n", ret);
389 regulator_disable(ssd130x->vcc_reg);
390 return ret;
391 }
392 }
393
394 return 0;
395 }
396
ssd130x_power_off(struct ssd130x_device * ssd130x)397 static void ssd130x_power_off(struct ssd130x_device *ssd130x)
398 {
399 pwm_disable(ssd130x->pwm);
400 pwm_put(ssd130x->pwm);
401
402 regulator_disable(ssd130x->vcc_reg);
403 }
404
ssd130x_init(struct ssd130x_device * ssd130x)405 static int ssd130x_init(struct ssd130x_device *ssd130x)
406 {
407 u32 precharge, dclk, com_invdir, compins, chargepump, seg_remap;
408 bool scan_mode;
409 int ret;
410
411 /* Set initial contrast */
412 ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_CONTRAST, ssd130x->contrast);
413 if (ret < 0)
414 return ret;
415
416 /* Set segment re-map */
417 seg_remap = (SSD13XX_SET_SEG_REMAP |
418 SSD13XX_SET_SEG_REMAP_SET(ssd130x->seg_remap));
419 ret = ssd130x_write_cmd(ssd130x, 1, seg_remap);
420 if (ret < 0)
421 return ret;
422
423 /* Set COM direction */
424 com_invdir = (SSD130X_SET_COM_SCAN_DIR |
425 SSD130X_SET_COM_SCAN_DIR_SET(ssd130x->com_invdir));
426 ret = ssd130x_write_cmd(ssd130x, 1, com_invdir);
427 if (ret < 0)
428 return ret;
429
430 /* Set multiplex ratio value */
431 ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
432 if (ret < 0)
433 return ret;
434
435 /* set display offset value */
436 ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_DISPLAY_OFFSET, ssd130x->com_offset);
437 if (ret < 0)
438 return ret;
439
440 /* Set clock frequency */
441 dclk = (SSD130X_SET_CLOCK_DIV_SET(ssd130x->dclk_div - 1) |
442 SSD130X_SET_CLOCK_FREQ_SET(ssd130x->dclk_frq));
443 ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_CLOCK_FREQ, dclk);
444 if (ret < 0)
445 return ret;
446
447 /* Set Area Color Mode ON/OFF & Low Power Display Mode */
448 if (ssd130x->area_color_enable || ssd130x->low_power) {
449 u32 mode = 0;
450
451 if (ssd130x->area_color_enable)
452 mode |= SSD130X_SET_AREA_COLOR_MODE_ENABLE;
453
454 if (ssd130x->low_power)
455 mode |= SSD130X_SET_AREA_COLOR_MODE_LOW_POWER;
456
457 ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_AREA_COLOR_MODE, mode);
458 if (ret < 0)
459 return ret;
460 }
461
462 /* Set precharge period in number of ticks from the internal clock */
463 precharge = (SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep1) |
464 SSD130X_SET_PRECHARGE_PERIOD2_SET(ssd130x->prechargep2));
465 ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_PRECHARGE_PERIOD, precharge);
466 if (ret < 0)
467 return ret;
468
469 /* Set COM pins configuration */
470 compins = BIT(1);
471 /*
472 * The COM scan mode field values are the inverse of the boolean DT
473 * property "solomon,com-seq". The value 0b means scan from COM0 to
474 * COM[N - 1] while 1b means scan from COM[N - 1] to COM0.
475 */
476 scan_mode = !ssd130x->com_seq;
477 compins |= (SSD130X_SET_COM_PINS_CONFIG1_SET(scan_mode) |
478 SSD130X_SET_COM_PINS_CONFIG2_SET(ssd130x->com_lrremap));
479 ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_COM_PINS_CONFIG, compins);
480 if (ret < 0)
481 return ret;
482
483 /* Set VCOMH */
484 ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_VCOMH, ssd130x->vcomh);
485 if (ret < 0)
486 return ret;
487
488 /* Turn on the DC-DC Charge Pump */
489 chargepump = BIT(4);
490
491 if (ssd130x->device_info->need_chargepump)
492 chargepump |= BIT(2);
493
494 ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CHARGE_PUMP, chargepump);
495 if (ret < 0)
496 return ret;
497
498 /* Set lookup table */
499 if (ssd130x->lookup_table_set) {
500 int i;
501
502 ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SET_LOOKUP_TABLE);
503 if (ret < 0)
504 return ret;
505
506 for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); i++) {
507 u8 val = ssd130x->lookup_table[i];
508
509 if (val < 31 || val > 63)
510 dev_warn(ssd130x->dev,
511 "lookup table index %d value out of range 31 <= %d <= 63\n",
512 i, val);
513 ret = ssd130x_write_cmd(ssd130x, 1, val);
514 if (ret < 0)
515 return ret;
516 }
517 }
518
519 /* Switch to page addressing mode */
520 if (ssd130x->page_address_mode)
521 return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
522 SSD130X_SET_ADDRESS_MODE_PAGE);
523
524 /* Switch to horizontal addressing mode */
525 return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
526 SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
527 }
528
ssd132x_init(struct ssd130x_device * ssd130x)529 static int ssd132x_init(struct ssd130x_device *ssd130x)
530 {
531 int ret;
532
533 /* Set initial contrast */
534 ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_CONTRAST, 0x80);
535 if (ret < 0)
536 return ret;
537
538 /* Set column start and end */
539 ret = ssd130x_write_cmd(ssd130x, 3, SSD132X_SET_COL_RANGE, 0x00,
540 ssd130x->width / SSD132X_SEGMENT_WIDTH - 1);
541 if (ret < 0)
542 return ret;
543
544 /* Set row start and end */
545 ret = ssd130x_write_cmd(ssd130x, 3, SSD132X_SET_ROW_RANGE, 0x00, ssd130x->height - 1);
546 if (ret < 0)
547 return ret;
548 /*
549 * Horizontal Address Increment
550 * Re-map for Column Address, Nibble and COM
551 * COM Split Odd Even
552 */
553 ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_SET_SEG_REMAP, 0x53);
554 if (ret < 0)
555 return ret;
556
557 /* Set display start and offset */
558 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_DISPLAY_START, 0x00);
559 if (ret < 0)
560 return ret;
561
562 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_DISPLAY_OFFSET, 0x00);
563 if (ret < 0)
564 return ret;
565
566 /* Set display mode normal */
567 ret = ssd130x_write_cmd(ssd130x, 1, SSD132X_SET_DISPLAY_NORMAL);
568 if (ret < 0)
569 return ret;
570
571 /* Set multiplex ratio value */
572 ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
573 if (ret < 0)
574 return ret;
575
576 /* Set phase length */
577 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PHASE_LENGTH, 0x55);
578 if (ret < 0)
579 return ret;
580
581 /* Select default linear gray scale table */
582 ret = ssd130x_write_cmd(ssd130x, 1, SSD132X_SELECT_DEFAULT_TABLE);
583 if (ret < 0)
584 return ret;
585
586 /* Set clock frequency */
587 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_CLOCK_FREQ, 0x01);
588 if (ret < 0)
589 return ret;
590
591 /* Enable internal VDD regulator */
592 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_FUNCTION_SELECT_A, 0x1);
593 if (ret < 0)
594 return ret;
595
596 /* Set pre-charge period */
597 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PRECHARGE_PERIOD, 0x01);
598 if (ret < 0)
599 return ret;
600
601 /* Set pre-charge voltage */
602 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PRECHARGE_VOLTAGE, 0x08);
603 if (ret < 0)
604 return ret;
605
606 /* Set VCOMH voltage */
607 ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_VCOMH_VOLTAGE, 0x07);
608 if (ret < 0)
609 return ret;
610
611 /* Enable second pre-charge and internal VSL */
612 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_FUNCTION_SELECT_B, 0x62);
613 if (ret < 0)
614 return ret;
615
616 return 0;
617 }
618
ssd133x_init(struct ssd130x_device * ssd130x)619 static int ssd133x_init(struct ssd130x_device *ssd130x)
620 {
621 int ret;
622
623 /* Set color A contrast */
624 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_A, 0x91);
625 if (ret < 0)
626 return ret;
627
628 /* Set color B contrast */
629 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_B, 0x50);
630 if (ret < 0)
631 return ret;
632
633 /* Set color C contrast */
634 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_CONTRAST_C, 0x7d);
635 if (ret < 0)
636 return ret;
637
638 /* Set master current */
639 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_MASTER_CURRENT, 0x06);
640 if (ret < 0)
641 return ret;
642
643 /* Set column start and end */
644 ret = ssd130x_write_cmd(ssd130x, 3, SSD133X_SET_COL_RANGE, 0x00, ssd130x->width - 1);
645 if (ret < 0)
646 return ret;
647
648 /* Set row start and end */
649 ret = ssd130x_write_cmd(ssd130x, 3, SSD133X_SET_ROW_RANGE, 0x00, ssd130x->height - 1);
650 if (ret < 0)
651 return ret;
652
653 /*
654 * Horizontal Address Increment
655 * Normal order SA,SB,SC (e.g. RGB)
656 * COM Split Odd Even
657 * 256 color format
658 */
659 ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_SET_SEG_REMAP, 0x20);
660 if (ret < 0)
661 return ret;
662
663 /* Set display start and offset */
664 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_DISPLAY_START, 0x00);
665 if (ret < 0)
666 return ret;
667
668 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_DISPLAY_OFFSET, 0x00);
669 if (ret < 0)
670 return ret;
671
672 /* Set display mode normal */
673 ret = ssd130x_write_cmd(ssd130x, 1, SSD133X_SET_DISPLAY_NORMAL);
674 if (ret < 0)
675 return ret;
676
677 /* Set multiplex ratio value */
678 ret = ssd130x_write_cmd(ssd130x, 2, SSD13XX_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
679 if (ret < 0)
680 return ret;
681
682 /* Set master configuration */
683 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_MASTER_CONFIG, 0x8e);
684 if (ret < 0)
685 return ret;
686
687 /* Set power mode */
688 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_POWER_SAVE_MODE, 0x0b);
689 if (ret < 0)
690 return ret;
691
692 /* Set Phase 1 and 2 period */
693 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_PHASES_PERIOD, 0x31);
694 if (ret < 0)
695 return ret;
696
697 /* Set clock divider */
698 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_CLOCK_FREQ, 0xf0);
699 if (ret < 0)
700 return ret;
701
702 /* Set pre-charge A */
703 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PRECHARGE_A, 0x64);
704 if (ret < 0)
705 return ret;
706
707 /* Set pre-charge B */
708 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PRECHARGE_B, 0x78);
709 if (ret < 0)
710 return ret;
711
712 /* Set pre-charge C */
713 ret = ssd130x_write_cmd(ssd130x, 2, SSD132X_SET_PRECHARGE_C, 0x64);
714 if (ret < 0)
715 return ret;
716
717 /* Set pre-charge level */
718 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_PRECHARGE_VOLTAGE, 0x3a);
719 if (ret < 0)
720 return ret;
721
722 /* Set VCOMH voltage */
723 ret = ssd130x_write_cmd(ssd130x, 2, SSD133X_SET_VCOMH_VOLTAGE, 0x3e);
724 if (ret < 0)
725 return ret;
726
727 return 0;
728 }
729
ssd130x_update_rect(struct ssd130x_device * ssd130x,struct drm_rect * rect,u8 * buf,u8 * data_array)730 static int ssd130x_update_rect(struct ssd130x_device *ssd130x,
731 struct drm_rect *rect, u8 *buf,
732 u8 *data_array)
733 {
734 unsigned int x = rect->x1;
735 unsigned int y = rect->y1;
736 unsigned int width = drm_rect_width(rect);
737 unsigned int height = drm_rect_height(rect);
738 unsigned int line_length = DIV_ROUND_UP(width, 8);
739 unsigned int page_height = SSD130X_PAGE_HEIGHT;
740 u8 page_start = ssd130x->page_offset + y / page_height;
741 unsigned int pages = DIV_ROUND_UP(height, page_height);
742 struct drm_device *drm = &ssd130x->drm;
743 u32 array_idx = 0;
744 int ret, i, j, k;
745
746 drm_WARN_ONCE(drm, y % page_height != 0, "y must be aligned to screen page\n");
747
748 /*
749 * The screen is divided in pages, each having a height of 8
750 * pixels, and the width of the screen. When sending a byte of
751 * data to the controller, it gives the 8 bits for the current
752 * column. I.e, the first byte are the 8 bits of the first
753 * column, then the 8 bits for the second column, etc.
754 *
755 *
756 * Representation of the screen, assuming it is 5 bits
757 * wide. Each letter-number combination is a bit that controls
758 * one pixel.
759 *
760 * A0 A1 A2 A3 A4
761 * B0 B1 B2 B3 B4
762 * C0 C1 C2 C3 C4
763 * D0 D1 D2 D3 D4
764 * E0 E1 E2 E3 E4
765 * F0 F1 F2 F3 F4
766 * G0 G1 G2 G3 G4
767 * H0 H1 H2 H3 H4
768 *
769 * If you want to update this screen, you need to send 5 bytes:
770 * (1) A0 B0 C0 D0 E0 F0 G0 H0
771 * (2) A1 B1 C1 D1 E1 F1 G1 H1
772 * (3) A2 B2 C2 D2 E2 F2 G2 H2
773 * (4) A3 B3 C3 D3 E3 F3 G3 H3
774 * (5) A4 B4 C4 D4 E4 F4 G4 H4
775 */
776
777 if (!ssd130x->page_address_mode) {
778 /* Set address range for horizontal addressing mode */
779 ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
780 if (ret < 0)
781 return ret;
782
783 ret = ssd130x_set_page_range(ssd130x, page_start, pages);
784 if (ret < 0)
785 return ret;
786 }
787
788 for (i = 0; i < pages; i++) {
789 int m = page_height;
790
791 /* Last page may be partial */
792 if (page_height * (y / page_height + i + 1) > ssd130x->height)
793 m = ssd130x->height % page_height;
794
795 for (j = 0; j < width; j++) {
796 u8 data = 0;
797
798 for (k = 0; k < m; k++) {
799 u32 idx = (page_height * i + k) * line_length + j / 8;
800 u8 byte = buf[idx];
801 u8 bit = (byte >> (j % 8)) & 1;
802
803 data |= bit << k;
804 }
805 data_array[array_idx++] = data;
806 }
807
808 /*
809 * In page addressing mode, the start address needs to be reset,
810 * and each page then needs to be written out separately.
811 */
812 if (ssd130x->page_address_mode) {
813 ret = ssd130x_set_page_pos(ssd130x,
814 page_start + i,
815 ssd130x->col_offset + x);
816 if (ret < 0)
817 return ret;
818
819 ret = ssd130x_write_data(ssd130x, data_array, width);
820 if (ret < 0)
821 return ret;
822
823 array_idx = 0;
824 }
825 }
826
827 /* Write out update in one go if we aren't using page addressing mode */
828 if (!ssd130x->page_address_mode)
829 ret = ssd130x_write_data(ssd130x, data_array, width * pages);
830
831 return ret;
832 }
833
ssd132x_update_rect(struct ssd130x_device * ssd130x,struct drm_rect * rect,u8 * buf,u8 * data_array)834 static int ssd132x_update_rect(struct ssd130x_device *ssd130x,
835 struct drm_rect *rect, u8 *buf,
836 u8 *data_array)
837 {
838 unsigned int x = rect->x1;
839 unsigned int y = rect->y1;
840 unsigned int segment_width = SSD132X_SEGMENT_WIDTH;
841 unsigned int width = drm_rect_width(rect);
842 unsigned int height = drm_rect_height(rect);
843 unsigned int columns = DIV_ROUND_UP(width, segment_width);
844 unsigned int rows = height;
845 struct drm_device *drm = &ssd130x->drm;
846 u32 array_idx = 0;
847 unsigned int i, j;
848 int ret;
849
850 drm_WARN_ONCE(drm, x % segment_width != 0, "x must be aligned to screen segment\n");
851
852 /*
853 * The screen is divided in Segment and Common outputs, where
854 * COM0 to COM[N - 1] are the rows and SEG0 to SEG[M - 1] are
855 * the columns.
856 *
857 * Each Segment has a 4-bit pixel and each Common output has a
858 * row of pixels. When using the (default) horizontal address
859 * increment mode, each byte of data sent to the controller has
860 * two Segments (e.g: SEG0 and SEG1) that are stored in the lower
861 * and higher nibbles of a single byte representing one column.
862 * That is, the first byte are SEG0 (D0[3:0]) and SEG1 (D0[7:4]),
863 * the second byte are SEG2 (D1[3:0]) and SEG3 (D1[7:4]) and so on.
864 */
865
866 /* Set column start and end */
867 ret = ssd130x_write_cmd(ssd130x, 3, SSD132X_SET_COL_RANGE, x / segment_width, columns - 1);
868 if (ret < 0)
869 return ret;
870
871 /* Set row start and end */
872 ret = ssd130x_write_cmd(ssd130x, 3, SSD132X_SET_ROW_RANGE, y, rows - 1);
873 if (ret < 0)
874 return ret;
875
876 for (i = 0; i < height; i++) {
877 /* Process pair of pixels and combine them into a single byte */
878 for (j = 0; j < width; j += segment_width) {
879 u8 n1 = buf[i * width + j];
880 u8 n2 = buf[i * width + j + 1];
881
882 data_array[array_idx++] = (n2 & 0xf0) | (n1 >> 4);
883 }
884 }
885
886 /* Write out update in one go since horizontal addressing mode is used */
887 ret = ssd130x_write_data(ssd130x, data_array, columns * rows);
888
889 return ret;
890 }
891
ssd133x_update_rect(struct ssd130x_device * ssd130x,struct drm_rect * rect,u8 * data_array,unsigned int pitch)892 static int ssd133x_update_rect(struct ssd130x_device *ssd130x,
893 struct drm_rect *rect, u8 *data_array,
894 unsigned int pitch)
895 {
896 unsigned int x = rect->x1;
897 unsigned int y = rect->y1;
898 unsigned int columns = drm_rect_width(rect);
899 unsigned int rows = drm_rect_height(rect);
900 int ret;
901
902 /*
903 * The screen is divided in Segment and Common outputs, where
904 * COM0 to COM[N - 1] are the rows and SEG0 to SEG[M - 1] are
905 * the columns.
906 *
907 * Each Segment has a 8-bit pixel and each Common output has a
908 * row of pixels. When using the (default) horizontal address
909 * increment mode, each byte of data sent to the controller has
910 * a Segment (e.g: SEG0).
911 *
912 * When using the 256 color depth format, each pixel contains 3
913 * sub-pixels for color A, B and C. These have 3 bit, 3 bit and
914 * 2 bits respectively.
915 */
916
917 /* Set column start and end */
918 ret = ssd130x_write_cmd(ssd130x, 3, SSD133X_SET_COL_RANGE, x, columns - 1);
919 if (ret < 0)
920 return ret;
921
922 /* Set row start and end */
923 ret = ssd130x_write_cmd(ssd130x, 3, SSD133X_SET_ROW_RANGE, y, rows - 1);
924 if (ret < 0)
925 return ret;
926
927 /* Write out update in one go since horizontal addressing mode is used */
928 ret = ssd130x_write_data(ssd130x, data_array, pitch * rows);
929
930 return ret;
931 }
932
ssd130x_clear_screen(struct ssd130x_device * ssd130x,u8 * data_array)933 static void ssd130x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
934 {
935 unsigned int pages = DIV_ROUND_UP(ssd130x->height, SSD130X_PAGE_HEIGHT);
936 unsigned int width = ssd130x->width;
937 int ret, i;
938
939 if (!ssd130x->page_address_mode) {
940 memset(data_array, 0, width * pages);
941
942 /* Set address range for horizontal addressing mode */
943 ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset, width);
944 if (ret < 0)
945 return;
946
947 ret = ssd130x_set_page_range(ssd130x, ssd130x->page_offset, pages);
948 if (ret < 0)
949 return;
950
951 /* Write out update in one go if we aren't using page addressing mode */
952 ssd130x_write_data(ssd130x, data_array, width * pages);
953 } else {
954 /*
955 * In page addressing mode, the start address needs to be reset,
956 * and each page then needs to be written out separately.
957 */
958 memset(data_array, 0, width);
959
960 for (i = 0; i < pages; i++) {
961 ret = ssd130x_set_page_pos(ssd130x,
962 ssd130x->page_offset + i,
963 ssd130x->col_offset);
964 if (ret < 0)
965 return;
966
967 ret = ssd130x_write_data(ssd130x, data_array, width);
968 if (ret < 0)
969 return;
970 }
971 }
972 }
973
ssd132x_clear_screen(struct ssd130x_device * ssd130x,u8 * data_array)974 static void ssd132x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
975 {
976 unsigned int columns = DIV_ROUND_UP(ssd130x->width, SSD132X_SEGMENT_WIDTH);
977 unsigned int height = ssd130x->height;
978
979 memset(data_array, 0, columns * height);
980
981 /* Write out update in one go since horizontal addressing mode is used */
982 ssd130x_write_data(ssd130x, data_array, columns * height);
983 }
984
ssd133x_clear_screen(struct ssd130x_device * ssd130x,u8 * data_array)985 static void ssd133x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
986 {
987 const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
988 unsigned int pitch;
989
990 if (!fi)
991 return;
992
993 pitch = drm_format_info_min_pitch(fi, 0, ssd130x->width);
994
995 memset(data_array, 0, pitch * ssd130x->height);
996
997 /* Write out update in one go since horizontal addressing mode is used */
998 ssd130x_write_data(ssd130x, data_array, pitch * ssd130x->height);
999 }
1000
ssd130x_fb_blit_rect(struct drm_framebuffer * fb,const struct iosys_map * vmap,struct drm_rect * rect,u8 * buf,u8 * data_array,struct drm_format_conv_state * fmtcnv_state)1001 static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb,
1002 const struct iosys_map *vmap,
1003 struct drm_rect *rect,
1004 u8 *buf, u8 *data_array,
1005 struct drm_format_conv_state *fmtcnv_state)
1006 {
1007 struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
1008 struct iosys_map dst;
1009 unsigned int dst_pitch;
1010 int ret = 0;
1011
1012 /* Align y to display page boundaries */
1013 rect->y1 = round_down(rect->y1, SSD130X_PAGE_HEIGHT);
1014 rect->y2 = min_t(unsigned int, round_up(rect->y2, SSD130X_PAGE_HEIGHT), ssd130x->height);
1015
1016 dst_pitch = DIV_ROUND_UP(drm_rect_width(rect), 8);
1017
1018 iosys_map_set_vaddr(&dst, buf);
1019 drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
1020
1021 ssd130x_update_rect(ssd130x, rect, buf, data_array);
1022
1023 return ret;
1024 }
1025
ssd132x_fb_blit_rect(struct drm_framebuffer * fb,const struct iosys_map * vmap,struct drm_rect * rect,u8 * buf,u8 * data_array,struct drm_format_conv_state * fmtcnv_state)1026 static int ssd132x_fb_blit_rect(struct drm_framebuffer *fb,
1027 const struct iosys_map *vmap,
1028 struct drm_rect *rect, u8 *buf,
1029 u8 *data_array,
1030 struct drm_format_conv_state *fmtcnv_state)
1031 {
1032 struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
1033 unsigned int dst_pitch;
1034 struct iosys_map dst;
1035 int ret = 0;
1036
1037 /* Align x to display segment boundaries */
1038 rect->x1 = round_down(rect->x1, SSD132X_SEGMENT_WIDTH);
1039 rect->x2 = min_t(unsigned int, round_up(rect->x2, SSD132X_SEGMENT_WIDTH),
1040 ssd130x->width);
1041
1042 dst_pitch = drm_rect_width(rect);
1043
1044 iosys_map_set_vaddr(&dst, buf);
1045 drm_fb_xrgb8888_to_gray8(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
1046
1047 ssd132x_update_rect(ssd130x, rect, buf, data_array);
1048
1049 return ret;
1050 }
1051
ssd133x_fb_blit_rect(struct drm_framebuffer * fb,const struct iosys_map * vmap,struct drm_rect * rect,u8 * data_array,struct drm_format_conv_state * fmtcnv_state)1052 static int ssd133x_fb_blit_rect(struct drm_framebuffer *fb,
1053 const struct iosys_map *vmap,
1054 struct drm_rect *rect, u8 *data_array,
1055 struct drm_format_conv_state *fmtcnv_state)
1056 {
1057 struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
1058 const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
1059 unsigned int dst_pitch;
1060 struct iosys_map dst;
1061 int ret = 0;
1062
1063 if (!fi)
1064 return -EINVAL;
1065
1066 dst_pitch = drm_format_info_min_pitch(fi, 0, drm_rect_width(rect));
1067
1068 iosys_map_set_vaddr(&dst, data_array);
1069 drm_fb_xrgb8888_to_rgb332(&dst, &dst_pitch, vmap, fb, rect, fmtcnv_state);
1070
1071 ssd133x_update_rect(ssd130x, rect, data_array, dst_pitch);
1072
1073 return ret;
1074 }
1075
ssd130x_primary_plane_atomic_check(struct drm_plane * plane,struct drm_atomic_state * state)1076 static int ssd130x_primary_plane_atomic_check(struct drm_plane *plane,
1077 struct drm_atomic_state *state)
1078 {
1079 struct drm_device *drm = plane->dev;
1080 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1081 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1082 struct ssd130x_plane_state *ssd130x_state = to_ssd130x_plane_state(plane_state);
1083 struct drm_shadow_plane_state *shadow_plane_state = &ssd130x_state->base;
1084 struct drm_crtc *crtc = plane_state->crtc;
1085 struct drm_crtc_state *crtc_state = NULL;
1086 const struct drm_format_info *fi;
1087 unsigned int pitch;
1088 int ret;
1089
1090 if (crtc)
1091 crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1092
1093 ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
1094 DRM_PLANE_NO_SCALING,
1095 DRM_PLANE_NO_SCALING,
1096 false, false);
1097 if (ret)
1098 return ret;
1099 else if (!plane_state->visible)
1100 return 0;
1101
1102 fi = drm_format_info(DRM_FORMAT_R1);
1103 if (!fi)
1104 return -EINVAL;
1105
1106 pitch = drm_format_info_min_pitch(fi, 0, ssd130x->width);
1107
1108 if (plane_state->fb->format != fi) {
1109 void *buf;
1110
1111 /* format conversion necessary; reserve buffer */
1112 buf = drm_format_conv_state_reserve(&shadow_plane_state->fmtcnv_state,
1113 pitch, GFP_KERNEL);
1114 if (!buf)
1115 return -ENOMEM;
1116 }
1117
1118 ssd130x_state->buffer = kcalloc(pitch, ssd130x->height, GFP_KERNEL);
1119 if (!ssd130x_state->buffer)
1120 return -ENOMEM;
1121
1122 return 0;
1123 }
1124
ssd132x_primary_plane_atomic_check(struct drm_plane * plane,struct drm_atomic_state * state)1125 static int ssd132x_primary_plane_atomic_check(struct drm_plane *plane,
1126 struct drm_atomic_state *state)
1127 {
1128 struct drm_device *drm = plane->dev;
1129 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1130 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1131 struct ssd130x_plane_state *ssd130x_state = to_ssd130x_plane_state(plane_state);
1132 struct drm_shadow_plane_state *shadow_plane_state = &ssd130x_state->base;
1133 struct drm_crtc *crtc = plane_state->crtc;
1134 struct drm_crtc_state *crtc_state = NULL;
1135 const struct drm_format_info *fi;
1136 unsigned int pitch;
1137 int ret;
1138
1139 if (crtc)
1140 crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1141
1142 ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
1143 DRM_PLANE_NO_SCALING,
1144 DRM_PLANE_NO_SCALING,
1145 false, false);
1146 if (ret)
1147 return ret;
1148 else if (!plane_state->visible)
1149 return 0;
1150
1151 fi = drm_format_info(DRM_FORMAT_R8);
1152 if (!fi)
1153 return -EINVAL;
1154
1155 pitch = drm_format_info_min_pitch(fi, 0, ssd130x->width);
1156
1157 if (plane_state->fb->format != fi) {
1158 void *buf;
1159
1160 /* format conversion necessary; reserve buffer */
1161 buf = drm_format_conv_state_reserve(&shadow_plane_state->fmtcnv_state,
1162 pitch, GFP_KERNEL);
1163 if (!buf)
1164 return -ENOMEM;
1165 }
1166
1167 ssd130x_state->buffer = kcalloc(pitch, ssd130x->height, GFP_KERNEL);
1168 if (!ssd130x_state->buffer)
1169 return -ENOMEM;
1170
1171 return 0;
1172 }
1173
ssd133x_primary_plane_atomic_check(struct drm_plane * plane,struct drm_atomic_state * state)1174 static int ssd133x_primary_plane_atomic_check(struct drm_plane *plane,
1175 struct drm_atomic_state *state)
1176 {
1177 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1178 struct drm_crtc *crtc = plane_state->crtc;
1179 struct drm_crtc_state *crtc_state = NULL;
1180 int ret;
1181
1182 if (crtc)
1183 crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1184
1185 ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
1186 DRM_PLANE_NO_SCALING,
1187 DRM_PLANE_NO_SCALING,
1188 false, false);
1189 if (ret)
1190 return ret;
1191 else if (!plane_state->visible)
1192 return 0;
1193
1194 return 0;
1195 }
1196
ssd130x_primary_plane_atomic_update(struct drm_plane * plane,struct drm_atomic_state * state)1197 static void ssd130x_primary_plane_atomic_update(struct drm_plane *plane,
1198 struct drm_atomic_state *state)
1199 {
1200 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1201 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
1202 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
1203 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
1204 struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
1205 struct ssd130x_plane_state *ssd130x_plane_state = to_ssd130x_plane_state(plane_state);
1206 struct drm_framebuffer *fb = plane_state->fb;
1207 struct drm_atomic_helper_damage_iter iter;
1208 struct drm_device *drm = plane->dev;
1209 struct drm_rect dst_clip;
1210 struct drm_rect damage;
1211 int idx;
1212
1213 if (!drm_dev_enter(drm, &idx))
1214 return;
1215
1216 if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
1217 goto out_drm_dev_exit;
1218
1219 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
1220 drm_atomic_for_each_plane_damage(&iter, &damage) {
1221 dst_clip = plane_state->dst;
1222
1223 if (!drm_rect_intersect(&dst_clip, &damage))
1224 continue;
1225
1226 ssd130x_fb_blit_rect(fb, &shadow_plane_state->data[0], &dst_clip,
1227 ssd130x_plane_state->buffer,
1228 ssd130x_crtc_state->data_array,
1229 &shadow_plane_state->fmtcnv_state);
1230 }
1231
1232 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
1233
1234 out_drm_dev_exit:
1235 drm_dev_exit(idx);
1236 }
1237
ssd132x_primary_plane_atomic_update(struct drm_plane * plane,struct drm_atomic_state * state)1238 static void ssd132x_primary_plane_atomic_update(struct drm_plane *plane,
1239 struct drm_atomic_state *state)
1240 {
1241 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1242 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
1243 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
1244 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
1245 struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
1246 struct ssd130x_plane_state *ssd130x_plane_state = to_ssd130x_plane_state(plane_state);
1247 struct drm_framebuffer *fb = plane_state->fb;
1248 struct drm_atomic_helper_damage_iter iter;
1249 struct drm_device *drm = plane->dev;
1250 struct drm_rect dst_clip;
1251 struct drm_rect damage;
1252 int idx;
1253
1254 if (!drm_dev_enter(drm, &idx))
1255 return;
1256
1257 if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
1258 goto out_drm_dev_exit;
1259
1260 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
1261 drm_atomic_for_each_plane_damage(&iter, &damage) {
1262 dst_clip = plane_state->dst;
1263
1264 if (!drm_rect_intersect(&dst_clip, &damage))
1265 continue;
1266
1267 ssd132x_fb_blit_rect(fb, &shadow_plane_state->data[0], &dst_clip,
1268 ssd130x_plane_state->buffer,
1269 ssd130x_crtc_state->data_array,
1270 &shadow_plane_state->fmtcnv_state);
1271 }
1272
1273 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
1274
1275 out_drm_dev_exit:
1276 drm_dev_exit(idx);
1277 }
1278
ssd133x_primary_plane_atomic_update(struct drm_plane * plane,struct drm_atomic_state * state)1279 static void ssd133x_primary_plane_atomic_update(struct drm_plane *plane,
1280 struct drm_atomic_state *state)
1281 {
1282 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1283 struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
1284 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
1285 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
1286 struct ssd130x_crtc_state *ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
1287 struct drm_framebuffer *fb = plane_state->fb;
1288 struct drm_atomic_helper_damage_iter iter;
1289 struct drm_device *drm = plane->dev;
1290 struct drm_rect dst_clip;
1291 struct drm_rect damage;
1292 int idx;
1293
1294 if (!drm_dev_enter(drm, &idx))
1295 return;
1296
1297 if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
1298 goto out_drm_dev_exit;
1299
1300 drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
1301 drm_atomic_for_each_plane_damage(&iter, &damage) {
1302 dst_clip = plane_state->dst;
1303
1304 if (!drm_rect_intersect(&dst_clip, &damage))
1305 continue;
1306
1307 ssd133x_fb_blit_rect(fb, &shadow_plane_state->data[0], &dst_clip,
1308 ssd130x_crtc_state->data_array,
1309 &shadow_plane_state->fmtcnv_state);
1310 }
1311
1312 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
1313
1314 out_drm_dev_exit:
1315 drm_dev_exit(idx);
1316 }
1317
ssd130x_primary_plane_atomic_disable(struct drm_plane * plane,struct drm_atomic_state * state)1318 static void ssd130x_primary_plane_atomic_disable(struct drm_plane *plane,
1319 struct drm_atomic_state *state)
1320 {
1321 struct drm_device *drm = plane->dev;
1322 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1323 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1324 struct drm_crtc_state *crtc_state;
1325 struct ssd130x_crtc_state *ssd130x_crtc_state;
1326 int idx;
1327
1328 if (!plane_state->crtc)
1329 return;
1330
1331 crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
1332 ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
1333
1334 if (!drm_dev_enter(drm, &idx))
1335 return;
1336
1337 ssd130x_clear_screen(ssd130x, ssd130x_crtc_state->data_array);
1338
1339 drm_dev_exit(idx);
1340 }
1341
ssd132x_primary_plane_atomic_disable(struct drm_plane * plane,struct drm_atomic_state * state)1342 static void ssd132x_primary_plane_atomic_disable(struct drm_plane *plane,
1343 struct drm_atomic_state *state)
1344 {
1345 struct drm_device *drm = plane->dev;
1346 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1347 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1348 struct drm_crtc_state *crtc_state;
1349 struct ssd130x_crtc_state *ssd130x_crtc_state;
1350 int idx;
1351
1352 if (!plane_state->crtc)
1353 return;
1354
1355 crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
1356 ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
1357
1358 if (!drm_dev_enter(drm, &idx))
1359 return;
1360
1361 ssd132x_clear_screen(ssd130x, ssd130x_crtc_state->data_array);
1362
1363 drm_dev_exit(idx);
1364 }
1365
ssd133x_primary_plane_atomic_disable(struct drm_plane * plane,struct drm_atomic_state * state)1366 static void ssd133x_primary_plane_atomic_disable(struct drm_plane *plane,
1367 struct drm_atomic_state *state)
1368 {
1369 struct drm_device *drm = plane->dev;
1370 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1371 struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
1372 struct drm_crtc_state *crtc_state;
1373 struct ssd130x_crtc_state *ssd130x_crtc_state;
1374 int idx;
1375
1376 if (!plane_state->crtc)
1377 return;
1378
1379 crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
1380 ssd130x_crtc_state = to_ssd130x_crtc_state(crtc_state);
1381
1382 if (!drm_dev_enter(drm, &idx))
1383 return;
1384
1385 ssd133x_clear_screen(ssd130x, ssd130x_crtc_state->data_array);
1386
1387 drm_dev_exit(idx);
1388 }
1389
1390 /* Called during init to allocate the plane's atomic state. */
ssd130x_primary_plane_reset(struct drm_plane * plane)1391 static void ssd130x_primary_plane_reset(struct drm_plane *plane)
1392 {
1393 struct ssd130x_plane_state *ssd130x_state;
1394
1395 drm_WARN_ON_ONCE(plane->dev, plane->state);
1396
1397 ssd130x_state = kzalloc_obj(*ssd130x_state);
1398 if (!ssd130x_state)
1399 return;
1400
1401 __drm_gem_reset_shadow_plane(plane, &ssd130x_state->base);
1402 }
1403
ssd130x_primary_plane_duplicate_state(struct drm_plane * plane)1404 static struct drm_plane_state *ssd130x_primary_plane_duplicate_state(struct drm_plane *plane)
1405 {
1406 struct drm_shadow_plane_state *new_shadow_plane_state;
1407 struct ssd130x_plane_state *old_ssd130x_state;
1408 struct ssd130x_plane_state *ssd130x_state;
1409
1410 if (drm_WARN_ON_ONCE(plane->dev, !plane->state))
1411 return NULL;
1412
1413 old_ssd130x_state = to_ssd130x_plane_state(plane->state);
1414 ssd130x_state = kmemdup(old_ssd130x_state, sizeof(*ssd130x_state), GFP_KERNEL);
1415 if (!ssd130x_state)
1416 return NULL;
1417
1418 /* The buffer is not duplicated and is allocated in .atomic_check */
1419 ssd130x_state->buffer = NULL;
1420
1421 new_shadow_plane_state = &ssd130x_state->base;
1422
1423 __drm_gem_duplicate_shadow_plane_state(plane, new_shadow_plane_state);
1424
1425 return &new_shadow_plane_state->base;
1426 }
1427
ssd130x_primary_plane_destroy_state(struct drm_plane * plane,struct drm_plane_state * state)1428 static void ssd130x_primary_plane_destroy_state(struct drm_plane *plane,
1429 struct drm_plane_state *state)
1430 {
1431 struct ssd130x_plane_state *ssd130x_state = to_ssd130x_plane_state(state);
1432
1433 kfree(ssd130x_state->buffer);
1434
1435 __drm_gem_destroy_shadow_plane_state(&ssd130x_state->base);
1436
1437 kfree(ssd130x_state);
1438 }
1439
1440 static const struct drm_plane_helper_funcs ssd130x_primary_plane_helper_funcs[] = {
1441 [SSD130X_FAMILY] = {
1442 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
1443 .atomic_check = ssd130x_primary_plane_atomic_check,
1444 .atomic_update = ssd130x_primary_plane_atomic_update,
1445 .atomic_disable = ssd130x_primary_plane_atomic_disable,
1446 },
1447 [SSD132X_FAMILY] = {
1448 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
1449 .atomic_check = ssd132x_primary_plane_atomic_check,
1450 .atomic_update = ssd132x_primary_plane_atomic_update,
1451 .atomic_disable = ssd132x_primary_plane_atomic_disable,
1452 },
1453 [SSD133X_FAMILY] = {
1454 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
1455 .atomic_check = ssd133x_primary_plane_atomic_check,
1456 .atomic_update = ssd133x_primary_plane_atomic_update,
1457 .atomic_disable = ssd133x_primary_plane_atomic_disable,
1458 }
1459 };
1460
1461 static const struct drm_plane_funcs ssd130x_primary_plane_funcs = {
1462 .update_plane = drm_atomic_helper_update_plane,
1463 .disable_plane = drm_atomic_helper_disable_plane,
1464 .reset = ssd130x_primary_plane_reset,
1465 .atomic_duplicate_state = ssd130x_primary_plane_duplicate_state,
1466 .atomic_destroy_state = ssd130x_primary_plane_destroy_state,
1467 .destroy = drm_plane_cleanup,
1468 };
1469
ssd130x_crtc_mode_valid(struct drm_crtc * crtc,const struct drm_display_mode * mode)1470 static enum drm_mode_status ssd130x_crtc_mode_valid(struct drm_crtc *crtc,
1471 const struct drm_display_mode *mode)
1472 {
1473 struct ssd130x_device *ssd130x = drm_to_ssd130x(crtc->dev);
1474
1475 return drm_crtc_helper_mode_valid_fixed(crtc, mode, &ssd130x->mode);
1476 }
1477
ssd130x_crtc_atomic_check(struct drm_crtc * crtc,struct drm_atomic_state * state)1478 static int ssd130x_crtc_atomic_check(struct drm_crtc *crtc,
1479 struct drm_atomic_state *state)
1480 {
1481 struct drm_device *drm = crtc->dev;
1482 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1483 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1484 struct ssd130x_crtc_state *ssd130x_state = to_ssd130x_crtc_state(crtc_state);
1485 unsigned int pages = DIV_ROUND_UP(ssd130x->height, SSD130X_PAGE_HEIGHT);
1486 int ret;
1487
1488 ret = drm_crtc_helper_atomic_check(crtc, state);
1489 if (ret)
1490 return ret;
1491
1492 ssd130x_state->data_array = kmalloc_array(ssd130x->width, pages, GFP_KERNEL);
1493 if (!ssd130x_state->data_array)
1494 return -ENOMEM;
1495
1496 return 0;
1497 }
1498
ssd132x_crtc_atomic_check(struct drm_crtc * crtc,struct drm_atomic_state * state)1499 static int ssd132x_crtc_atomic_check(struct drm_crtc *crtc,
1500 struct drm_atomic_state *state)
1501 {
1502 struct drm_device *drm = crtc->dev;
1503 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1504 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1505 struct ssd130x_crtc_state *ssd130x_state = to_ssd130x_crtc_state(crtc_state);
1506 unsigned int columns = DIV_ROUND_UP(ssd130x->width, SSD132X_SEGMENT_WIDTH);
1507 int ret;
1508
1509 ret = drm_crtc_helper_atomic_check(crtc, state);
1510 if (ret)
1511 return ret;
1512
1513 ssd130x_state->data_array = kmalloc_array(columns, ssd130x->height, GFP_KERNEL);
1514 if (!ssd130x_state->data_array)
1515 return -ENOMEM;
1516
1517 return 0;
1518 }
1519
ssd133x_crtc_atomic_check(struct drm_crtc * crtc,struct drm_atomic_state * state)1520 static int ssd133x_crtc_atomic_check(struct drm_crtc *crtc,
1521 struct drm_atomic_state *state)
1522 {
1523 struct drm_device *drm = crtc->dev;
1524 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1525 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1526 struct ssd130x_crtc_state *ssd130x_state = to_ssd130x_crtc_state(crtc_state);
1527 const struct drm_format_info *fi = drm_format_info(DRM_FORMAT_RGB332);
1528 unsigned int pitch;
1529 int ret;
1530
1531 if (!fi)
1532 return -EINVAL;
1533
1534 ret = drm_crtc_helper_atomic_check(crtc, state);
1535 if (ret)
1536 return ret;
1537
1538 pitch = drm_format_info_min_pitch(fi, 0, ssd130x->width);
1539
1540 ssd130x_state->data_array = kmalloc_array(pitch, ssd130x->height, GFP_KERNEL);
1541 if (!ssd130x_state->data_array)
1542 return -ENOMEM;
1543
1544 return 0;
1545 }
1546
1547 /* Called during init to allocate the CRTC's atomic state. */
ssd130x_crtc_reset(struct drm_crtc * crtc)1548 static void ssd130x_crtc_reset(struct drm_crtc *crtc)
1549 {
1550 struct ssd130x_crtc_state *ssd130x_state;
1551
1552 drm_WARN_ON_ONCE(crtc->dev, crtc->state);
1553
1554 ssd130x_state = kzalloc_obj(*ssd130x_state);
1555 if (!ssd130x_state)
1556 return;
1557
1558 __drm_atomic_helper_crtc_reset(crtc, &ssd130x_state->base);
1559 }
1560
ssd130x_crtc_duplicate_state(struct drm_crtc * crtc)1561 static struct drm_crtc_state *ssd130x_crtc_duplicate_state(struct drm_crtc *crtc)
1562 {
1563 struct ssd130x_crtc_state *old_ssd130x_state;
1564 struct ssd130x_crtc_state *ssd130x_state;
1565
1566 if (drm_WARN_ON_ONCE(crtc->dev, !crtc->state))
1567 return NULL;
1568
1569 old_ssd130x_state = to_ssd130x_crtc_state(crtc->state);
1570 ssd130x_state = kmemdup(old_ssd130x_state, sizeof(*ssd130x_state), GFP_KERNEL);
1571 if (!ssd130x_state)
1572 return NULL;
1573
1574 /* The buffer is not duplicated and is allocated in .atomic_check */
1575 ssd130x_state->data_array = NULL;
1576
1577 __drm_atomic_helper_crtc_duplicate_state(crtc, &ssd130x_state->base);
1578
1579 return &ssd130x_state->base;
1580 }
1581
ssd130x_crtc_destroy_state(struct drm_crtc * crtc,struct drm_crtc_state * state)1582 static void ssd130x_crtc_destroy_state(struct drm_crtc *crtc,
1583 struct drm_crtc_state *state)
1584 {
1585 struct ssd130x_crtc_state *ssd130x_state = to_ssd130x_crtc_state(state);
1586
1587 kfree(ssd130x_state->data_array);
1588
1589 __drm_atomic_helper_crtc_destroy_state(state);
1590
1591 kfree(ssd130x_state);
1592 }
1593
1594 /*
1595 * The CRTC is always enabled. Screen updates are performed by
1596 * the primary plane's atomic_update function. Disabling clears
1597 * the screen in the primary plane's atomic_disable function.
1598 */
1599 static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs[] = {
1600 [SSD130X_FAMILY] = {
1601 .mode_valid = ssd130x_crtc_mode_valid,
1602 .atomic_check = ssd130x_crtc_atomic_check,
1603 },
1604 [SSD132X_FAMILY] = {
1605 .mode_valid = ssd130x_crtc_mode_valid,
1606 .atomic_check = ssd132x_crtc_atomic_check,
1607 },
1608 [SSD133X_FAMILY] = {
1609 .mode_valid = ssd130x_crtc_mode_valid,
1610 .atomic_check = ssd133x_crtc_atomic_check,
1611 },
1612 };
1613
1614 static const struct drm_crtc_funcs ssd130x_crtc_funcs = {
1615 .reset = ssd130x_crtc_reset,
1616 .destroy = drm_crtc_cleanup,
1617 .set_config = drm_atomic_helper_set_config,
1618 .page_flip = drm_atomic_helper_page_flip,
1619 .atomic_duplicate_state = ssd130x_crtc_duplicate_state,
1620 .atomic_destroy_state = ssd130x_crtc_destroy_state,
1621 };
1622
ssd130x_encoder_atomic_enable(struct drm_encoder * encoder,struct drm_atomic_state * state)1623 static void ssd130x_encoder_atomic_enable(struct drm_encoder *encoder,
1624 struct drm_atomic_state *state)
1625 {
1626 struct drm_device *drm = encoder->dev;
1627 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1628 int ret;
1629
1630 ret = ssd130x_power_on(ssd130x);
1631 if (ret)
1632 return;
1633
1634 ret = ssd130x_init(ssd130x);
1635 if (ret)
1636 goto power_off;
1637
1638 ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
1639
1640 backlight_enable(ssd130x->bl_dev);
1641
1642 return;
1643
1644 power_off:
1645 ssd130x_power_off(ssd130x);
1646 return;
1647 }
1648
ssd132x_encoder_atomic_enable(struct drm_encoder * encoder,struct drm_atomic_state * state)1649 static void ssd132x_encoder_atomic_enable(struct drm_encoder *encoder,
1650 struct drm_atomic_state *state)
1651 {
1652 struct drm_device *drm = encoder->dev;
1653 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1654 int ret;
1655
1656 ret = ssd130x_power_on(ssd130x);
1657 if (ret)
1658 return;
1659
1660 ret = ssd132x_init(ssd130x);
1661 if (ret)
1662 goto power_off;
1663
1664 ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
1665
1666 backlight_enable(ssd130x->bl_dev);
1667
1668 return;
1669
1670 power_off:
1671 ssd130x_power_off(ssd130x);
1672 }
1673
ssd133x_encoder_atomic_enable(struct drm_encoder * encoder,struct drm_atomic_state * state)1674 static void ssd133x_encoder_atomic_enable(struct drm_encoder *encoder,
1675 struct drm_atomic_state *state)
1676 {
1677 struct drm_device *drm = encoder->dev;
1678 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1679 int ret;
1680
1681 ret = ssd130x_power_on(ssd130x);
1682 if (ret)
1683 return;
1684
1685 ret = ssd133x_init(ssd130x);
1686 if (ret)
1687 goto power_off;
1688
1689 ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_ON);
1690
1691 backlight_enable(ssd130x->bl_dev);
1692
1693 return;
1694
1695 power_off:
1696 ssd130x_power_off(ssd130x);
1697 }
1698
ssd130x_encoder_atomic_disable(struct drm_encoder * encoder,struct drm_atomic_state * state)1699 static void ssd130x_encoder_atomic_disable(struct drm_encoder *encoder,
1700 struct drm_atomic_state *state)
1701 {
1702 struct drm_device *drm = encoder->dev;
1703 struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
1704
1705 backlight_disable(ssd130x->bl_dev);
1706
1707 ssd130x_write_cmd(ssd130x, 1, SSD13XX_DISPLAY_OFF);
1708
1709 ssd130x_power_off(ssd130x);
1710 }
1711
1712 static const struct drm_encoder_helper_funcs ssd130x_encoder_helper_funcs[] = {
1713 [SSD130X_FAMILY] = {
1714 .atomic_enable = ssd130x_encoder_atomic_enable,
1715 .atomic_disable = ssd130x_encoder_atomic_disable,
1716 },
1717 [SSD132X_FAMILY] = {
1718 .atomic_enable = ssd132x_encoder_atomic_enable,
1719 .atomic_disable = ssd130x_encoder_atomic_disable,
1720 },
1721 [SSD133X_FAMILY] = {
1722 .atomic_enable = ssd133x_encoder_atomic_enable,
1723 .atomic_disable = ssd130x_encoder_atomic_disable,
1724 }
1725 };
1726
1727 static const struct drm_encoder_funcs ssd130x_encoder_funcs = {
1728 .destroy = drm_encoder_cleanup,
1729 };
1730
ssd130x_connector_get_modes(struct drm_connector * connector)1731 static int ssd130x_connector_get_modes(struct drm_connector *connector)
1732 {
1733 struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev);
1734
1735 return drm_connector_helper_get_modes_fixed(connector, &ssd130x->mode);
1736 }
1737
1738 static const struct drm_connector_helper_funcs ssd130x_connector_helper_funcs = {
1739 .get_modes = ssd130x_connector_get_modes,
1740 };
1741
1742 static const struct drm_connector_funcs ssd130x_connector_funcs = {
1743 .reset = drm_atomic_helper_connector_reset,
1744 .fill_modes = drm_helper_probe_single_connector_modes,
1745 .destroy = drm_connector_cleanup,
1746 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1747 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1748 };
1749
1750 static const struct drm_mode_config_funcs ssd130x_mode_config_funcs = {
1751 .fb_create = drm_gem_fb_create_with_dirty,
1752 .atomic_check = drm_atomic_helper_check,
1753 .atomic_commit = drm_atomic_helper_commit,
1754 };
1755
1756 static const uint32_t ssd130x_formats[] = {
1757 DRM_FORMAT_XRGB8888,
1758 };
1759
1760 DEFINE_DRM_GEM_FOPS(ssd130x_fops);
1761
1762 static const struct drm_driver ssd130x_drm_driver = {
1763 DRM_GEM_SHMEM_DRIVER_OPS,
1764 DRM_FBDEV_SHMEM_DRIVER_OPS,
1765 .name = DRIVER_NAME,
1766 .desc = DRIVER_DESC,
1767 .major = DRIVER_MAJOR,
1768 .minor = DRIVER_MINOR,
1769 .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
1770 .fops = &ssd130x_fops,
1771 };
1772
ssd130x_update_bl(struct backlight_device * bdev)1773 static int ssd130x_update_bl(struct backlight_device *bdev)
1774 {
1775 struct ssd130x_device *ssd130x = bl_get_data(bdev);
1776 int brightness = backlight_get_brightness(bdev);
1777 int ret;
1778
1779 ssd130x->contrast = brightness;
1780
1781 ret = ssd130x_write_cmd(ssd130x, 1, SSD13XX_CONTRAST);
1782 if (ret < 0)
1783 return ret;
1784
1785 ret = ssd130x_write_cmd(ssd130x, 1, ssd130x->contrast);
1786 if (ret < 0)
1787 return ret;
1788
1789 return 0;
1790 }
1791
1792 static const struct backlight_ops ssd130xfb_bl_ops = {
1793 .update_status = ssd130x_update_bl,
1794 };
1795
ssd130x_parse_properties(struct ssd130x_device * ssd130x)1796 static void ssd130x_parse_properties(struct ssd130x_device *ssd130x)
1797 {
1798 struct device *dev = ssd130x->dev;
1799
1800 if (device_property_read_u32(dev, "solomon,width", &ssd130x->width))
1801 ssd130x->width = ssd130x->device_info->default_width;
1802
1803 if (device_property_read_u32(dev, "solomon,height", &ssd130x->height))
1804 ssd130x->height = ssd130x->device_info->default_height;
1805
1806 if (device_property_read_u32(dev, "solomon,page-offset", &ssd130x->page_offset))
1807 ssd130x->page_offset = 1;
1808
1809 if (device_property_read_u32(dev, "solomon,col-offset", &ssd130x->col_offset))
1810 ssd130x->col_offset = 0;
1811
1812 if (device_property_read_u32(dev, "solomon,com-offset", &ssd130x->com_offset))
1813 ssd130x->com_offset = 0;
1814
1815 if (device_property_read_u32(dev, "solomon,prechargep1", &ssd130x->prechargep1))
1816 ssd130x->prechargep1 = 2;
1817
1818 if (device_property_read_u32(dev, "solomon,prechargep2", &ssd130x->prechargep2))
1819 ssd130x->prechargep2 = 2;
1820
1821 if (!device_property_read_u8_array(dev, "solomon,lookup-table",
1822 ssd130x->lookup_table,
1823 ARRAY_SIZE(ssd130x->lookup_table)))
1824 ssd130x->lookup_table_set = 1;
1825
1826 ssd130x->seg_remap = !device_property_read_bool(dev, "solomon,segment-no-remap");
1827 ssd130x->com_seq = device_property_read_bool(dev, "solomon,com-seq");
1828 ssd130x->com_lrremap = device_property_read_bool(dev, "solomon,com-lrremap");
1829 ssd130x->com_invdir = device_property_read_bool(dev, "solomon,com-invdir");
1830 ssd130x->area_color_enable =
1831 device_property_read_bool(dev, "solomon,area-color-enable");
1832 ssd130x->low_power = device_property_read_bool(dev, "solomon,low-power");
1833
1834 ssd130x->contrast = 127;
1835 ssd130x->vcomh = ssd130x->device_info->default_vcomh;
1836
1837 /* Setup display timing */
1838 if (device_property_read_u32(dev, "solomon,dclk-div", &ssd130x->dclk_div))
1839 ssd130x->dclk_div = ssd130x->device_info->default_dclk_div;
1840 if (device_property_read_u32(dev, "solomon,dclk-frq", &ssd130x->dclk_frq))
1841 ssd130x->dclk_frq = ssd130x->device_info->default_dclk_frq;
1842 }
1843
ssd130x_init_modeset(struct ssd130x_device * ssd130x)1844 static int ssd130x_init_modeset(struct ssd130x_device *ssd130x)
1845 {
1846 enum ssd130x_family_ids family_id = ssd130x->device_info->family_id;
1847 struct drm_display_mode *mode = &ssd130x->mode;
1848 struct device *dev = ssd130x->dev;
1849 struct drm_device *drm = &ssd130x->drm;
1850 unsigned long max_width, max_height;
1851 struct drm_plane *primary_plane;
1852 struct drm_crtc *crtc;
1853 struct drm_encoder *encoder;
1854 struct drm_connector *connector;
1855 int ret;
1856
1857 /*
1858 * Modesetting
1859 */
1860
1861 ret = drmm_mode_config_init(drm);
1862 if (ret) {
1863 dev_err(dev, "DRM mode config init failed: %d\n", ret);
1864 return ret;
1865 }
1866
1867 mode->type = DRM_MODE_TYPE_DRIVER;
1868 mode->clock = 1;
1869 mode->hdisplay = ssd130x->width;
1870 mode->htotal = ssd130x->width;
1871 mode->hsync_start = ssd130x->width;
1872 mode->hsync_end = ssd130x->width;
1873 mode->vdisplay = ssd130x->height;
1874 mode->vtotal = ssd130x->height;
1875 mode->vsync_start = ssd130x->height;
1876 mode->vsync_end = ssd130x->height;
1877 mode->width_mm = 27;
1878 mode->height_mm = 27;
1879
1880 max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH);
1881 max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT);
1882
1883 drm->mode_config.min_width = mode->hdisplay;
1884 drm->mode_config.max_width = max_width;
1885 drm->mode_config.min_height = mode->vdisplay;
1886 drm->mode_config.max_height = max_height;
1887 drm->mode_config.preferred_depth = 24;
1888 drm->mode_config.funcs = &ssd130x_mode_config_funcs;
1889
1890 /* Primary plane */
1891
1892 primary_plane = &ssd130x->primary_plane;
1893 ret = drm_universal_plane_init(drm, primary_plane, 0, &ssd130x_primary_plane_funcs,
1894 ssd130x_formats, ARRAY_SIZE(ssd130x_formats),
1895 NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
1896 if (ret) {
1897 dev_err(dev, "DRM primary plane init failed: %d\n", ret);
1898 return ret;
1899 }
1900
1901 drm_plane_helper_add(primary_plane, &ssd130x_primary_plane_helper_funcs[family_id]);
1902
1903 drm_plane_enable_fb_damage_clips(primary_plane);
1904
1905 /* CRTC */
1906
1907 crtc = &ssd130x->crtc;
1908 ret = drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
1909 &ssd130x_crtc_funcs, NULL);
1910 if (ret) {
1911 dev_err(dev, "DRM crtc init failed: %d\n", ret);
1912 return ret;
1913 }
1914
1915 drm_crtc_helper_add(crtc, &ssd130x_crtc_helper_funcs[family_id]);
1916
1917 /* Encoder */
1918
1919 encoder = &ssd130x->encoder;
1920 ret = drm_encoder_init(drm, encoder, &ssd130x_encoder_funcs,
1921 DRM_MODE_ENCODER_NONE, NULL);
1922 if (ret) {
1923 dev_err(dev, "DRM encoder init failed: %d\n", ret);
1924 return ret;
1925 }
1926
1927 drm_encoder_helper_add(encoder, &ssd130x_encoder_helper_funcs[family_id]);
1928
1929 encoder->possible_crtcs = drm_crtc_mask(crtc);
1930
1931 /* Connector */
1932
1933 connector = &ssd130x->connector;
1934 ret = drm_connector_init(drm, connector, &ssd130x_connector_funcs,
1935 DRM_MODE_CONNECTOR_Unknown);
1936 if (ret) {
1937 dev_err(dev, "DRM connector init failed: %d\n", ret);
1938 return ret;
1939 }
1940
1941 drm_connector_helper_add(connector, &ssd130x_connector_helper_funcs);
1942
1943 ret = drm_connector_attach_encoder(connector, encoder);
1944 if (ret) {
1945 dev_err(dev, "DRM attach connector to encoder failed: %d\n", ret);
1946 return ret;
1947 }
1948
1949 drm_mode_config_reset(drm);
1950
1951 return 0;
1952 }
1953
ssd130x_get_resources(struct ssd130x_device * ssd130x)1954 static int ssd130x_get_resources(struct ssd130x_device *ssd130x)
1955 {
1956 struct device *dev = ssd130x->dev;
1957
1958 ssd130x->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
1959 if (IS_ERR(ssd130x->reset))
1960 return dev_err_probe(dev, PTR_ERR(ssd130x->reset),
1961 "Failed to get reset gpio\n");
1962
1963 ssd130x->vcc_reg = devm_regulator_get(dev, "vcc");
1964 if (IS_ERR(ssd130x->vcc_reg))
1965 return dev_err_probe(dev, PTR_ERR(ssd130x->vcc_reg),
1966 "Failed to get VCC regulator\n");
1967
1968 return 0;
1969 }
1970
ssd130x_probe(struct device * dev,struct regmap * regmap)1971 struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
1972 {
1973 struct ssd130x_device *ssd130x;
1974 struct backlight_device *bl;
1975 struct drm_device *drm;
1976 int ret;
1977
1978 ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
1979 struct ssd130x_device, drm);
1980 if (IS_ERR(ssd130x))
1981 return ERR_PTR(dev_err_probe(dev, PTR_ERR(ssd130x),
1982 "Failed to allocate DRM device\n"));
1983
1984 drm = &ssd130x->drm;
1985
1986 ssd130x->dev = dev;
1987 ssd130x->regmap = regmap;
1988 ssd130x->device_info = device_get_match_data(dev);
1989
1990 if (ssd130x->device_info->page_mode_only)
1991 ssd130x->page_address_mode = 1;
1992
1993 ssd130x_parse_properties(ssd130x);
1994
1995 ret = ssd130x_get_resources(ssd130x);
1996 if (ret)
1997 return ERR_PTR(ret);
1998
1999 bl = devm_backlight_device_register(dev, dev_name(dev), dev, ssd130x,
2000 &ssd130xfb_bl_ops, NULL);
2001 if (IS_ERR(bl))
2002 return ERR_PTR(dev_err_probe(dev, PTR_ERR(bl),
2003 "Unable to register backlight device\n"));
2004
2005 bl->props.brightness = ssd130x->contrast;
2006 bl->props.max_brightness = MAX_CONTRAST;
2007 ssd130x->bl_dev = bl;
2008
2009 ret = ssd130x_init_modeset(ssd130x);
2010 if (ret)
2011 return ERR_PTR(ret);
2012
2013 ret = drm_dev_register(drm, 0);
2014 if (ret)
2015 return ERR_PTR(dev_err_probe(dev, ret, "DRM device register failed\n"));
2016
2017 drm_client_setup(drm, NULL);
2018
2019 return ssd130x;
2020 }
2021 EXPORT_SYMBOL_GPL(ssd130x_probe);
2022
ssd130x_remove(struct ssd130x_device * ssd130x)2023 void ssd130x_remove(struct ssd130x_device *ssd130x)
2024 {
2025 drm_dev_unplug(&ssd130x->drm);
2026 drm_atomic_helper_shutdown(&ssd130x->drm);
2027 }
2028 EXPORT_SYMBOL_GPL(ssd130x_remove);
2029
ssd130x_shutdown(struct ssd130x_device * ssd130x)2030 void ssd130x_shutdown(struct ssd130x_device *ssd130x)
2031 {
2032 drm_atomic_helper_shutdown(&ssd130x->drm);
2033 }
2034 EXPORT_SYMBOL_GPL(ssd130x_shutdown);
2035
2036 MODULE_DESCRIPTION(DRIVER_DESC);
2037 MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
2038 MODULE_LICENSE("GPL v2");
2039