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