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