1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for the Solomon SSD1307 OLED controller 4 * 5 * Copyright 2012 Free Electrons 6 */ 7 8 #include <linux/backlight.h> 9 #include <linux/delay.h> 10 #include <linux/fb.h> 11 #include <linux/gpio/consumer.h> 12 #include <linux/i2c.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/property.h> 16 #include <linux/pwm.h> 17 #include <linux/spinlock.h> 18 #include <linux/uaccess.h> 19 #include <linux/regulator/consumer.h> 20 21 #define SSD1307FB_DATA 0x40 22 #define SSD1307FB_COMMAND 0x80 23 24 #define SSD1307FB_SET_ADDRESS_MODE 0x20 25 #define SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL (0x00) 26 #define SSD1307FB_SET_ADDRESS_MODE_VERTICAL (0x01) 27 #define SSD1307FB_SET_ADDRESS_MODE_PAGE (0x02) 28 #define SSD1307FB_SET_COL_RANGE 0x21 29 #define SSD1307FB_SET_PAGE_RANGE 0x22 30 #define SSD1307FB_CONTRAST 0x81 31 #define SSD1307FB_SET_LOOKUP_TABLE 0x91 32 #define SSD1307FB_CHARGE_PUMP 0x8d 33 #define SSD1307FB_SEG_REMAP_ON 0xa1 34 #define SSD1307FB_DISPLAY_OFF 0xae 35 #define SSD1307FB_SET_MULTIPLEX_RATIO 0xa8 36 #define SSD1307FB_DISPLAY_ON 0xaf 37 #define SSD1307FB_START_PAGE_ADDRESS 0xb0 38 #define SSD1307FB_SET_DISPLAY_OFFSET 0xd3 39 #define SSD1307FB_SET_CLOCK_FREQ 0xd5 40 #define SSD1307FB_SET_AREA_COLOR_MODE 0xd8 41 #define SSD1307FB_SET_PRECHARGE_PERIOD 0xd9 42 #define SSD1307FB_SET_COM_PINS_CONFIG 0xda 43 #define SSD1307FB_SET_VCOMH 0xdb 44 45 #define MAX_CONTRAST 255 46 47 #define REFRESHRATE 1 48 49 static u_int refreshrate = REFRESHRATE; 50 module_param(refreshrate, uint, 0); 51 52 struct ssd1307fb_deviceinfo { 53 u32 default_vcomh; 54 u32 default_dclk_div; 55 u32 default_dclk_frq; 56 bool need_pwm; 57 bool need_chargepump; 58 }; 59 60 struct ssd1307fb_par { 61 unsigned area_color_enable : 1; 62 unsigned com_invdir : 1; 63 unsigned com_lrremap : 1; 64 unsigned com_seq : 1; 65 unsigned lookup_table_set : 1; 66 unsigned low_power : 1; 67 unsigned seg_remap : 1; 68 u32 com_offset; 69 u32 contrast; 70 u32 dclk_div; 71 u32 dclk_frq; 72 const struct ssd1307fb_deviceinfo *device_info; 73 struct i2c_client *client; 74 u32 height; 75 struct fb_info *info; 76 /* Pending damage, with exclusive x2/y2, protected by damage_lock. */ 77 spinlock_t damage_lock; 78 bool damage_pending; 79 u32 damage_x1; 80 u32 damage_x2; 81 u32 damage_y1; 82 u32 damage_y2; 83 u8 lookup_table[4]; 84 u32 page_offset; 85 u32 col_offset; 86 u32 prechargep1; 87 u32 prechargep2; 88 struct pwm_device *pwm; 89 struct gpio_desc *reset; 90 struct regulator *vbat_reg; 91 u32 vcomh; 92 u32 width; 93 /* Cached address ranges */ 94 u8 col_start; 95 u8 col_end; 96 u8 page_start; 97 u8 page_end; 98 }; 99 100 struct ssd1307fb_array { 101 u8 type; 102 u8 data[]; 103 }; 104 105 static const struct fb_fix_screeninfo ssd1307fb_fix = { 106 .id = "Solomon SSD1307", 107 .type = FB_TYPE_PACKED_PIXELS, 108 .visual = FB_VISUAL_MONO10, 109 .xpanstep = 0, 110 .ypanstep = 0, 111 .ywrapstep = 0, 112 .accel = FB_ACCEL_NONE, 113 }; 114 115 static const struct fb_var_screeninfo ssd1307fb_var = { 116 .bits_per_pixel = 1, 117 .red = { .length = 1 }, 118 .green = { .length = 1 }, 119 .blue = { .length = 1 }, 120 }; 121 122 static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type) 123 { 124 struct ssd1307fb_array *array; 125 126 array = kzalloc(sizeof(struct ssd1307fb_array) + len, GFP_KERNEL); 127 if (!array) 128 return NULL; 129 130 array->type = type; 131 132 return array; 133 } 134 135 static int ssd1307fb_write_array(struct i2c_client *client, 136 struct ssd1307fb_array *array, u32 len) 137 { 138 int ret; 139 140 len += sizeof(struct ssd1307fb_array); 141 142 ret = i2c_master_send(client, (u8 *)array, len); 143 if (ret != len) { 144 dev_err(&client->dev, "Couldn't send I2C command.\n"); 145 return ret; 146 } 147 148 return 0; 149 } 150 151 static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd) 152 { 153 struct ssd1307fb_array *array; 154 int ret; 155 156 array = ssd1307fb_alloc_array(1, SSD1307FB_COMMAND); 157 if (!array) 158 return -ENOMEM; 159 160 array->data[0] = cmd; 161 162 ret = ssd1307fb_write_array(client, array, 1); 163 kfree(array); 164 165 return ret; 166 } 167 168 static int ssd1307fb_set_col_range(struct ssd1307fb_par *par, u8 col_start, 169 u8 cols) 170 { 171 u8 col_end = col_start + cols - 1; 172 int ret; 173 174 if (col_start == par->col_start && col_end == par->col_end) 175 return 0; 176 177 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE); 178 if (ret < 0) 179 return ret; 180 181 ret = ssd1307fb_write_cmd(par->client, col_start); 182 if (ret < 0) 183 return ret; 184 185 ret = ssd1307fb_write_cmd(par->client, col_end); 186 if (ret < 0) 187 return ret; 188 189 par->col_start = col_start; 190 par->col_end = col_end; 191 return 0; 192 } 193 194 static int ssd1307fb_set_page_range(struct ssd1307fb_par *par, u8 page_start, 195 u8 pages) 196 { 197 u8 page_end = page_start + pages - 1; 198 int ret; 199 200 if (page_start == par->page_start && page_end == par->page_end) 201 return 0; 202 203 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE); 204 if (ret < 0) 205 return ret; 206 207 ret = ssd1307fb_write_cmd(par->client, page_start); 208 if (ret < 0) 209 return ret; 210 211 ret = ssd1307fb_write_cmd(par->client, page_end); 212 if (ret < 0) 213 return ret; 214 215 par->page_start = page_start; 216 par->page_end = page_end; 217 return 0; 218 } 219 220 static int ssd1307fb_update_rect(struct ssd1307fb_par *par, unsigned int x, 221 unsigned int y, unsigned int width, 222 unsigned int height) 223 { 224 struct ssd1307fb_array *array; 225 u8 *vmem = par->info->screen_buffer; 226 unsigned int line_length = par->info->fix.line_length; 227 unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8); 228 u32 array_idx = 0; 229 int ret, i, j, k; 230 231 array = ssd1307fb_alloc_array(width * pages, SSD1307FB_DATA); 232 if (!array) 233 return -ENOMEM; 234 235 /* 236 * The screen is divided in pages, each having a height of 8 237 * pixels, and the width of the screen. When sending a byte of 238 * data to the controller, it gives the 8 bits for the current 239 * column. I.e, the first byte are the 8 bits of the first 240 * column, then the 8 bits for the second column, etc. 241 * 242 * 243 * Representation of the screen, assuming it is 5 bits 244 * wide. Each letter-number combination is a bit that controls 245 * one pixel. 246 * 247 * A0 A1 A2 A3 A4 248 * B0 B1 B2 B3 B4 249 * C0 C1 C2 C3 C4 250 * D0 D1 D2 D3 D4 251 * E0 E1 E2 E3 E4 252 * F0 F1 F2 F3 F4 253 * G0 G1 G2 G3 G4 254 * H0 H1 H2 H3 H4 255 * 256 * If you want to update this screen, you need to send 5 bytes: 257 * (1) A0 B0 C0 D0 E0 F0 G0 H0 258 * (2) A1 B1 C1 D1 E1 F1 G1 H1 259 * (3) A2 B2 C2 D2 E2 F2 G2 H2 260 * (4) A3 B3 C3 D3 E3 F3 G3 H3 261 * (5) A4 B4 C4 D4 E4 F4 G4 H4 262 */ 263 264 ret = ssd1307fb_set_col_range(par, par->col_offset + x, width); 265 if (ret < 0) 266 goto out_free; 267 268 ret = ssd1307fb_set_page_range(par, par->page_offset + y / 8, pages); 269 if (ret < 0) 270 goto out_free; 271 272 for (i = y / 8; i < y / 8 + pages; i++) { 273 int m = 8; 274 275 /* Last page may be partial */ 276 if (8 * (i + 1) > par->height) 277 m = par->height % 8; 278 for (j = x; j < x + width; j++) { 279 u8 data = 0; 280 281 for (k = 0; k < m; k++) { 282 u8 byte = vmem[(8 * i + k) * line_length + 283 j / 8]; 284 u8 bit = (byte >> (j % 8)) & 1; 285 data |= bit << k; 286 } 287 array->data[array_idx++] = data; 288 } 289 } 290 291 ret = ssd1307fb_write_array(par->client, array, width * pages); 292 293 out_free: 294 kfree(array); 295 return ret; 296 } 297 298 static int ssd1307fb_update_display(struct ssd1307fb_par *par) 299 { 300 return ssd1307fb_update_rect(par, 0, 0, par->width, par->height); 301 } 302 303 static int ssd1307fb_blank(int blank_mode, struct fb_info *info) 304 { 305 struct ssd1307fb_par *par = info->par; 306 307 if (blank_mode != FB_BLANK_UNBLANK) 308 return ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF); 309 else 310 return ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); 311 } 312 313 static void ssd1307fb_schedule_damage(struct fb_info *info, u32 x, u32 y, 314 u32 width, u32 height) 315 { 316 struct ssd1307fb_par *par = info->par; 317 unsigned long flags; 318 u32 x2, y2; 319 320 if (!width || !height || x >= par->width || y >= par->height) 321 return; 322 323 x2 = x + min(width, par->width - x); 324 y2 = y + min(height, par->height - y); 325 326 spin_lock_irqsave(&par->damage_lock, flags); 327 if (par->damage_pending) { 328 par->damage_x1 = min(par->damage_x1, x); 329 par->damage_y1 = min(par->damage_y1, y); 330 par->damage_x2 = max(par->damage_x2, x2); 331 par->damage_y2 = max(par->damage_y2, y2); 332 } else { 333 par->damage_x1 = x; 334 par->damage_y1 = y; 335 par->damage_x2 = x2; 336 par->damage_y2 = y2; 337 par->damage_pending = true; 338 } 339 spin_unlock_irqrestore(&par->damage_lock, flags); 340 341 /* Advance an already-pending mmap update as well. */ 342 mod_delayed_work(system_wq, &info->deferred_work, 0); 343 } 344 345 static void ssd1307fb_defio_damage_range(struct fb_info *info, off_t off, size_t len) 346 { 347 struct ssd1307fb_par *par = info->par; 348 349 ssd1307fb_schedule_damage(info, 0, 0, par->width, par->height); 350 } 351 352 static void ssd1307fb_defio_damage_area(struct fb_info *info, u32 x, u32 y, 353 u32 width, u32 height) 354 { 355 ssd1307fb_schedule_damage(info, x, y, width, height); 356 } 357 358 FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(ssd1307fb, 359 ssd1307fb_defio_damage_range, 360 ssd1307fb_defio_damage_area) 361 362 static const struct fb_ops ssd1307fb_ops = { 363 .owner = THIS_MODULE, 364 FB_DEFAULT_DEFERRED_OPS(ssd1307fb), 365 .fb_blank = ssd1307fb_blank, 366 }; 367 368 static void ssd1307fb_deferred_io(struct fb_info *info, struct list_head *pagereflist) 369 { 370 struct ssd1307fb_par *par = info->par; 371 unsigned long flags; 372 u32 x, y, width, height; 373 374 spin_lock_irqsave(&par->damage_lock, flags); 375 if (!list_empty(pagereflist)) { 376 x = 0; 377 y = 0; 378 width = par->width; 379 height = par->height; 380 par->damage_pending = false; 381 } else if (par->damage_pending) { 382 x = par->damage_x1; 383 y = par->damage_y1; 384 width = par->damage_x2 - par->damage_x1; 385 height = par->damage_y2 - par->damage_y1; 386 par->damage_pending = false; 387 } else { 388 spin_unlock_irqrestore(&par->damage_lock, flags); 389 return; 390 } 391 spin_unlock_irqrestore(&par->damage_lock, flags); 392 393 ssd1307fb_update_rect(par, x, y, width, height); 394 } 395 396 static int ssd1307fb_init(struct ssd1307fb_par *par) 397 { 398 struct pwm_state pwmstate; 399 int ret; 400 u32 precharge, dclk, com_invdir, compins; 401 402 if (par->device_info->need_pwm) { 403 par->pwm = pwm_get(&par->client->dev, NULL); 404 if (IS_ERR(par->pwm)) { 405 dev_err(&par->client->dev, "Could not get PWM from device tree!\n"); 406 return PTR_ERR(par->pwm); 407 } 408 409 pwm_init_state(par->pwm, &pwmstate); 410 pwm_set_relative_duty_cycle(&pwmstate, 50, 100); 411 pwm_apply_might_sleep(par->pwm, &pwmstate); 412 413 /* Enable the PWM */ 414 pwm_enable(par->pwm); 415 416 dev_dbg(&par->client->dev, "Using PWM %s with a %lluns period.\n", 417 par->pwm->label, pwm_get_period(par->pwm)); 418 } 419 420 /* Set initial contrast */ 421 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST); 422 if (ret < 0) 423 return ret; 424 425 ret = ssd1307fb_write_cmd(par->client, par->contrast); 426 if (ret < 0) 427 return ret; 428 429 /* Set segment re-map */ 430 if (par->seg_remap) { 431 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON); 432 if (ret < 0) 433 return ret; 434 } 435 436 /* Set COM direction */ 437 com_invdir = 0xc0 | par->com_invdir << 3; 438 ret = ssd1307fb_write_cmd(par->client, com_invdir); 439 if (ret < 0) 440 return ret; 441 442 /* Set multiplex ratio value */ 443 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO); 444 if (ret < 0) 445 return ret; 446 447 ret = ssd1307fb_write_cmd(par->client, par->height - 1); 448 if (ret < 0) 449 return ret; 450 451 /* set display offset value */ 452 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET); 453 if (ret < 0) 454 return ret; 455 456 ret = ssd1307fb_write_cmd(par->client, par->com_offset); 457 if (ret < 0) 458 return ret; 459 460 /* Set clock frequency */ 461 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ); 462 if (ret < 0) 463 return ret; 464 465 dclk = ((par->dclk_div - 1) & 0xf) | (par->dclk_frq & 0xf) << 4; 466 ret = ssd1307fb_write_cmd(par->client, dclk); 467 if (ret < 0) 468 return ret; 469 470 /* Set Area Color Mode ON/OFF & Low Power Display Mode */ 471 if (par->area_color_enable || par->low_power) { 472 u32 mode; 473 474 ret = ssd1307fb_write_cmd(par->client, 475 SSD1307FB_SET_AREA_COLOR_MODE); 476 if (ret < 0) 477 return ret; 478 479 mode = (par->area_color_enable ? 0x30 : 0) | 480 (par->low_power ? 5 : 0); 481 ret = ssd1307fb_write_cmd(par->client, mode); 482 if (ret < 0) 483 return ret; 484 } 485 486 /* Set precharge period in number of ticks from the internal clock */ 487 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD); 488 if (ret < 0) 489 return ret; 490 491 precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4; 492 ret = ssd1307fb_write_cmd(par->client, precharge); 493 if (ret < 0) 494 return ret; 495 496 /* Set COM pins configuration */ 497 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG); 498 if (ret < 0) 499 return ret; 500 501 compins = 0x02 | !par->com_seq << 4 | par->com_lrremap << 5; 502 ret = ssd1307fb_write_cmd(par->client, compins); 503 if (ret < 0) 504 return ret; 505 506 /* Set VCOMH */ 507 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH); 508 if (ret < 0) 509 return ret; 510 511 ret = ssd1307fb_write_cmd(par->client, par->vcomh); 512 if (ret < 0) 513 return ret; 514 515 /* Turn on the DC-DC Charge Pump */ 516 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP); 517 if (ret < 0) 518 return ret; 519 520 ret = ssd1307fb_write_cmd(par->client, 521 BIT(4) | (par->device_info->need_chargepump ? BIT(2) : 0)); 522 if (ret < 0) 523 return ret; 524 525 /* Set lookup table */ 526 if (par->lookup_table_set) { 527 int i; 528 529 ret = ssd1307fb_write_cmd(par->client, 530 SSD1307FB_SET_LOOKUP_TABLE); 531 if (ret < 0) 532 return ret; 533 534 for (i = 0; i < ARRAY_SIZE(par->lookup_table); ++i) { 535 u8 val = par->lookup_table[i]; 536 537 if (val < 31 || val > 63) 538 dev_warn(&par->client->dev, 539 "lookup table index %d value out of range 31 <= %d <= 63\n", 540 i, val); 541 ret = ssd1307fb_write_cmd(par->client, val); 542 if (ret < 0) 543 return ret; 544 } 545 } 546 547 /* Switch to horizontal addressing mode */ 548 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE); 549 if (ret < 0) 550 return ret; 551 552 ret = ssd1307fb_write_cmd(par->client, 553 SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL); 554 if (ret < 0) 555 return ret; 556 557 /* Clear the screen */ 558 ret = ssd1307fb_update_display(par); 559 if (ret < 0) 560 return ret; 561 562 /* Turn on the display */ 563 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); 564 if (ret < 0) 565 return ret; 566 567 return 0; 568 } 569 570 static int ssd1307fb_update_bl(struct backlight_device *bdev) 571 { 572 struct ssd1307fb_par *par = bl_get_data(bdev); 573 int ret; 574 int brightness = bdev->props.brightness; 575 576 par->contrast = brightness; 577 578 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST); 579 if (ret < 0) 580 return ret; 581 ret = ssd1307fb_write_cmd(par->client, par->contrast); 582 if (ret < 0) 583 return ret; 584 return 0; 585 } 586 587 static int ssd1307fb_get_brightness(struct backlight_device *bdev) 588 { 589 struct ssd1307fb_par *par = bl_get_data(bdev); 590 591 return par->contrast; 592 } 593 594 static const struct backlight_ops ssd1307fb_bl_ops = { 595 .options = BL_CORE_SUSPENDRESUME, 596 .update_status = ssd1307fb_update_bl, 597 .get_brightness = ssd1307fb_get_brightness, 598 }; 599 600 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = { 601 .default_vcomh = 0x34, 602 .default_dclk_div = 1, 603 .default_dclk_frq = 7, 604 }; 605 606 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = { 607 .default_vcomh = 0x20, 608 .default_dclk_div = 1, 609 .default_dclk_frq = 8, 610 .need_chargepump = 1, 611 }; 612 613 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = { 614 .default_vcomh = 0x20, 615 .default_dclk_div = 2, 616 .default_dclk_frq = 12, 617 .need_pwm = 1, 618 }; 619 620 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1309_deviceinfo = { 621 .default_vcomh = 0x34, 622 .default_dclk_div = 1, 623 .default_dclk_frq = 10, 624 }; 625 626 static const struct of_device_id ssd1307fb_of_match[] = { 627 { 628 .compatible = "solomon,ssd1305fb-i2c", 629 .data = (void *)&ssd1307fb_ssd1305_deviceinfo, 630 }, 631 { 632 .compatible = "solomon,ssd1306fb-i2c", 633 .data = (void *)&ssd1307fb_ssd1306_deviceinfo, 634 }, 635 { 636 .compatible = "solomon,ssd1307fb-i2c", 637 .data = (void *)&ssd1307fb_ssd1307_deviceinfo, 638 }, 639 { 640 .compatible = "solomon,ssd1309fb-i2c", 641 .data = (void *)&ssd1307fb_ssd1309_deviceinfo, 642 }, 643 {}, 644 }; 645 MODULE_DEVICE_TABLE(of, ssd1307fb_of_match); 646 647 static int ssd1307fb_probe(struct i2c_client *client) 648 { 649 struct device *dev = &client->dev; 650 struct backlight_device *bl; 651 struct fb_info *info; 652 struct fb_deferred_io *ssd1307fb_defio; 653 u32 vmem_size; 654 struct ssd1307fb_par *par; 655 void *vmem; 656 int ret; 657 658 info = framebuffer_alloc(sizeof(struct ssd1307fb_par), dev); 659 if (!info) 660 return -ENOMEM; 661 662 par = info->par; 663 par->info = info; 664 par->client = client; 665 spin_lock_init(&par->damage_lock); 666 667 par->device_info = device_get_match_data(dev); 668 669 par->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 670 if (IS_ERR(par->reset)) { 671 ret = dev_err_probe(dev, PTR_ERR(par->reset), 672 "failed to get reset gpio\n"); 673 goto fb_alloc_error; 674 } 675 676 par->vbat_reg = devm_regulator_get_optional(dev, "vbat"); 677 if (IS_ERR(par->vbat_reg)) { 678 ret = PTR_ERR(par->vbat_reg); 679 if (ret == -ENODEV) { 680 par->vbat_reg = NULL; 681 } else { 682 dev_err_probe(dev, ret, "failed to get VBAT regulator\n"); 683 goto fb_alloc_error; 684 } 685 } 686 687 if (device_property_read_u32(dev, "solomon,width", &par->width)) 688 par->width = 96; 689 690 if (device_property_read_u32(dev, "solomon,height", &par->height)) 691 par->height = 16; 692 693 if (device_property_read_u32(dev, "solomon,page-offset", &par->page_offset)) 694 par->page_offset = 1; 695 696 if (device_property_read_u32(dev, "solomon,col-offset", &par->col_offset)) 697 par->col_offset = 0; 698 699 if (device_property_read_u32(dev, "solomon,com-offset", &par->com_offset)) 700 par->com_offset = 0; 701 702 if (device_property_read_u32(dev, "solomon,prechargep1", &par->prechargep1)) 703 par->prechargep1 = 2; 704 705 if (device_property_read_u32(dev, "solomon,prechargep2", &par->prechargep2)) 706 par->prechargep2 = 2; 707 708 if (!device_property_read_u8_array(dev, "solomon,lookup-table", 709 par->lookup_table, 710 ARRAY_SIZE(par->lookup_table))) 711 par->lookup_table_set = 1; 712 713 par->seg_remap = !device_property_read_bool(dev, "solomon,segment-no-remap"); 714 par->com_seq = device_property_read_bool(dev, "solomon,com-seq"); 715 par->com_lrremap = device_property_read_bool(dev, "solomon,com-lrremap"); 716 par->com_invdir = device_property_read_bool(dev, "solomon,com-invdir"); 717 par->area_color_enable = 718 device_property_read_bool(dev, "solomon,area-color-enable"); 719 par->low_power = device_property_read_bool(dev, "solomon,low-power"); 720 721 par->contrast = 127; 722 par->vcomh = par->device_info->default_vcomh; 723 724 /* Setup display timing */ 725 if (device_property_read_u32(dev, "solomon,dclk-div", &par->dclk_div)) 726 par->dclk_div = par->device_info->default_dclk_div; 727 if (device_property_read_u32(dev, "solomon,dclk-frq", &par->dclk_frq)) 728 par->dclk_frq = par->device_info->default_dclk_frq; 729 730 vmem_size = DIV_ROUND_UP(par->width, 8) * par->height; 731 732 vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 733 get_order(vmem_size)); 734 if (!vmem) { 735 dev_err(dev, "Couldn't allocate graphical memory.\n"); 736 ret = -ENOMEM; 737 goto fb_alloc_error; 738 } 739 740 ssd1307fb_defio = devm_kzalloc(dev, sizeof(*ssd1307fb_defio), 741 GFP_KERNEL); 742 if (!ssd1307fb_defio) { 743 dev_err(dev, "Couldn't allocate deferred io.\n"); 744 ret = -ENOMEM; 745 goto fb_defio_error; 746 } 747 748 ssd1307fb_defio->delay = HZ / refreshrate; 749 ssd1307fb_defio->deferred_io = ssd1307fb_deferred_io; 750 751 info->fbops = &ssd1307fb_ops; 752 info->fix = ssd1307fb_fix; 753 info->fix.line_length = DIV_ROUND_UP(par->width, 8); 754 info->fbdefio = ssd1307fb_defio; 755 756 info->var = ssd1307fb_var; 757 info->var.xres = par->width; 758 info->var.xres_virtual = par->width; 759 info->var.yres = par->height; 760 info->var.yres_virtual = par->height; 761 762 info->screen_buffer = vmem; 763 info->fix.smem_start = __pa(vmem); 764 info->fix.smem_len = vmem_size; 765 766 fb_deferred_io_init(info); 767 768 i2c_set_clientdata(client, info); 769 770 if (par->reset) { 771 /* Reset the screen */ 772 gpiod_set_value_cansleep(par->reset, 1); 773 udelay(4); 774 gpiod_set_value_cansleep(par->reset, 0); 775 udelay(4); 776 } 777 778 if (par->vbat_reg) { 779 ret = regulator_enable(par->vbat_reg); 780 if (ret) { 781 dev_err(dev, "failed to enable VBAT: %d\n", ret); 782 goto reset_oled_error; 783 } 784 } 785 786 ret = ssd1307fb_init(par); 787 if (ret) 788 goto regulator_enable_error; 789 790 bl = backlight_device_register("ssd1307fb-bl", dev, par, &ssd1307fb_bl_ops, 791 NULL); 792 if (IS_ERR(bl)) { 793 ret = PTR_ERR(bl); 794 dev_err(dev, "unable to register backlight device: %d\n", ret); 795 goto panel_init_error; 796 } 797 info->bl_dev = bl; 798 799 ret = register_framebuffer(info); 800 if (ret) { 801 dev_err(dev, "Couldn't register the framebuffer\n"); 802 goto fb_init_error; 803 } 804 805 bl->props.brightness = par->contrast; 806 bl->props.max_brightness = MAX_CONTRAST; 807 808 dev_info(dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size); 809 810 return 0; 811 812 fb_init_error: 813 backlight_device_unregister(bl); 814 panel_init_error: 815 pwm_disable(par->pwm); 816 pwm_put(par->pwm); 817 regulator_enable_error: 818 if (par->vbat_reg) 819 regulator_disable(par->vbat_reg); 820 reset_oled_error: 821 fb_deferred_io_cleanup(info); 822 fb_defio_error: 823 __free_pages(vmem, get_order(vmem_size)); 824 fb_alloc_error: 825 framebuffer_release(info); 826 return ret; 827 } 828 829 static void ssd1307fb_remove(struct i2c_client *client) 830 { 831 struct fb_info *info = i2c_get_clientdata(client); 832 struct ssd1307fb_par *par = info->par; 833 834 ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF); 835 836 backlight_device_unregister(info->bl_dev); 837 838 unregister_framebuffer(info); 839 pwm_disable(par->pwm); 840 pwm_put(par->pwm); 841 if (par->vbat_reg) 842 regulator_disable(par->vbat_reg); 843 fb_deferred_io_cleanup(info); 844 __free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len)); 845 framebuffer_release(info); 846 } 847 848 static const struct i2c_device_id ssd1307fb_i2c_id[] = { 849 { .name = "ssd1305fb" }, 850 { .name = "ssd1306fb" }, 851 { .name = "ssd1307fb" }, 852 { .name = "ssd1309fb" }, 853 { } 854 }; 855 MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id); 856 857 static struct i2c_driver ssd1307fb_driver = { 858 .probe = ssd1307fb_probe, 859 .remove = ssd1307fb_remove, 860 .id_table = ssd1307fb_i2c_id, 861 .driver = { 862 .name = "ssd1307fb", 863 .of_match_table = ssd1307fb_of_match, 864 }, 865 }; 866 867 module_i2c_driver(ssd1307fb_driver); 868 869 MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controller"); 870 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 871 MODULE_LICENSE("GPL"); 872