Merge tag 'arm-dt-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / drivers / gpu / drm / solomon / ssd130x.c
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_PERIOD2_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");