1 /* 2 * Driver for the Solomon SSD1307 OLED controller 3 * 4 * Copyright 2012 Free Electrons 5 * 6 * Licensed under the GPLv2 or later. 7 */ 8 9 #include <linux/backlight.h> 10 #include <linux/delay.h> 11 #include <linux/fb.h> 12 #include <linux/gpio/consumer.h> 13 #include <linux/i2c.h> 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/of_device.h> 17 #include <linux/of_gpio.h> 18 #include <linux/pwm.h> 19 #include <linux/uaccess.h> 20 #include <linux/regulator/consumer.h> 21 22 #define SSD1307FB_DATA 0x40 23 #define SSD1307FB_COMMAND 0x80 24 25 #define SSD1307FB_SET_ADDRESS_MODE 0x20 26 #define SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL (0x00) 27 #define SSD1307FB_SET_ADDRESS_MODE_VERTICAL (0x01) 28 #define SSD1307FB_SET_ADDRESS_MODE_PAGE (0x02) 29 #define SSD1307FB_SET_COL_RANGE 0x21 30 #define SSD1307FB_SET_PAGE_RANGE 0x22 31 #define SSD1307FB_CONTRAST 0x81 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_PRECHARGE_PERIOD 0xd9 41 #define SSD1307FB_SET_COM_PINS_CONFIG 0xda 42 #define SSD1307FB_SET_VCOMH 0xdb 43 44 #define MAX_CONTRAST 255 45 46 #define REFRESHRATE 1 47 48 static u_int refreshrate = REFRESHRATE; 49 module_param(refreshrate, uint, 0); 50 51 struct ssd1307fb_par; 52 53 struct ssd1307fb_deviceinfo { 54 u32 default_vcomh; 55 u32 default_dclk_div; 56 u32 default_dclk_frq; 57 int need_pwm; 58 int need_chargepump; 59 }; 60 61 struct ssd1307fb_par { 62 u32 com_invdir; 63 u32 com_lrremap; 64 u32 com_offset; 65 u32 com_seq; 66 u32 contrast; 67 u32 dclk_div; 68 u32 dclk_frq; 69 const struct ssd1307fb_deviceinfo *device_info; 70 struct i2c_client *client; 71 u32 height; 72 struct fb_info *info; 73 u32 page_offset; 74 u32 prechargep1; 75 u32 prechargep2; 76 struct pwm_device *pwm; 77 u32 pwm_period; 78 struct gpio_desc *reset; 79 struct regulator *vbat_reg; 80 u32 seg_remap; 81 u32 vcomh; 82 u32 width; 83 }; 84 85 struct ssd1307fb_array { 86 u8 type; 87 u8 data[0]; 88 }; 89 90 static const struct fb_fix_screeninfo ssd1307fb_fix = { 91 .id = "Solomon SSD1307", 92 .type = FB_TYPE_PACKED_PIXELS, 93 .visual = FB_VISUAL_MONO10, 94 .xpanstep = 0, 95 .ypanstep = 0, 96 .ywrapstep = 0, 97 .accel = FB_ACCEL_NONE, 98 }; 99 100 static const struct fb_var_screeninfo ssd1307fb_var = { 101 .bits_per_pixel = 1, 102 }; 103 104 static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type) 105 { 106 struct ssd1307fb_array *array; 107 108 array = kzalloc(sizeof(struct ssd1307fb_array) + len, GFP_KERNEL); 109 if (!array) 110 return NULL; 111 112 array->type = type; 113 114 return array; 115 } 116 117 static int ssd1307fb_write_array(struct i2c_client *client, 118 struct ssd1307fb_array *array, u32 len) 119 { 120 int ret; 121 122 len += sizeof(struct ssd1307fb_array); 123 124 ret = i2c_master_send(client, (u8 *)array, len); 125 if (ret != len) { 126 dev_err(&client->dev, "Couldn't send I2C command.\n"); 127 return ret; 128 } 129 130 return 0; 131 } 132 133 static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd) 134 { 135 struct ssd1307fb_array *array; 136 int ret; 137 138 array = ssd1307fb_alloc_array(1, SSD1307FB_COMMAND); 139 if (!array) 140 return -ENOMEM; 141 142 array->data[0] = cmd; 143 144 ret = ssd1307fb_write_array(client, array, 1); 145 kfree(array); 146 147 return ret; 148 } 149 150 static void ssd1307fb_update_display(struct ssd1307fb_par *par) 151 { 152 struct ssd1307fb_array *array; 153 u8 *vmem = par->info->screen_base; 154 int i, j, k; 155 156 array = ssd1307fb_alloc_array(par->width * par->height / 8, 157 SSD1307FB_DATA); 158 if (!array) 159 return; 160 161 /* 162 * The screen is divided in pages, each having a height of 8 163 * pixels, and the width of the screen. When sending a byte of 164 * data to the controller, it gives the 8 bits for the current 165 * column. I.e, the first byte are the 8 bits of the first 166 * column, then the 8 bits for the second column, etc. 167 * 168 * 169 * Representation of the screen, assuming it is 5 bits 170 * wide. Each letter-number combination is a bit that controls 171 * one pixel. 172 * 173 * A0 A1 A2 A3 A4 174 * B0 B1 B2 B3 B4 175 * C0 C1 C2 C3 C4 176 * D0 D1 D2 D3 D4 177 * E0 E1 E2 E3 E4 178 * F0 F1 F2 F3 F4 179 * G0 G1 G2 G3 G4 180 * H0 H1 H2 H3 H4 181 * 182 * If you want to update this screen, you need to send 5 bytes: 183 * (1) A0 B0 C0 D0 E0 F0 G0 H0 184 * (2) A1 B1 C1 D1 E1 F1 G1 H1 185 * (3) A2 B2 C2 D2 E2 F2 G2 H2 186 * (4) A3 B3 C3 D3 E3 F3 G3 H3 187 * (5) A4 B4 C4 D4 E4 F4 G4 H4 188 */ 189 190 for (i = 0; i < (par->height / 8); i++) { 191 for (j = 0; j < par->width; j++) { 192 u32 array_idx = i * par->width + j; 193 array->data[array_idx] = 0; 194 for (k = 0; k < 8; k++) { 195 u32 page_length = par->width * i; 196 u32 index = page_length + (par->width * k + j) / 8; 197 u8 byte = *(vmem + index); 198 u8 bit = byte & (1 << (j % 8)); 199 bit = bit >> (j % 8); 200 array->data[array_idx] |= bit << k; 201 } 202 } 203 } 204 205 ssd1307fb_write_array(par->client, array, par->width * par->height / 8); 206 kfree(array); 207 } 208 209 210 static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf, 211 size_t count, loff_t *ppos) 212 { 213 struct ssd1307fb_par *par = info->par; 214 unsigned long total_size; 215 unsigned long p = *ppos; 216 u8 __iomem *dst; 217 218 total_size = info->fix.smem_len; 219 220 if (p > total_size) 221 return -EINVAL; 222 223 if (count + p > total_size) 224 count = total_size - p; 225 226 if (!count) 227 return -EINVAL; 228 229 dst = (void __force *) (info->screen_base + p); 230 231 if (copy_from_user(dst, buf, count)) 232 return -EFAULT; 233 234 ssd1307fb_update_display(par); 235 236 *ppos += count; 237 238 return count; 239 } 240 241 static int ssd1307fb_blank(int blank_mode, struct fb_info *info) 242 { 243 struct ssd1307fb_par *par = info->par; 244 245 if (blank_mode != FB_BLANK_UNBLANK) 246 return ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF); 247 else 248 return ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); 249 } 250 251 static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 252 { 253 struct ssd1307fb_par *par = info->par; 254 sys_fillrect(info, rect); 255 ssd1307fb_update_display(par); 256 } 257 258 static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 259 { 260 struct ssd1307fb_par *par = info->par; 261 sys_copyarea(info, area); 262 ssd1307fb_update_display(par); 263 } 264 265 static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image) 266 { 267 struct ssd1307fb_par *par = info->par; 268 sys_imageblit(info, image); 269 ssd1307fb_update_display(par); 270 } 271 272 static struct fb_ops ssd1307fb_ops = { 273 .owner = THIS_MODULE, 274 .fb_read = fb_sys_read, 275 .fb_write = ssd1307fb_write, 276 .fb_blank = ssd1307fb_blank, 277 .fb_fillrect = ssd1307fb_fillrect, 278 .fb_copyarea = ssd1307fb_copyarea, 279 .fb_imageblit = ssd1307fb_imageblit, 280 }; 281 282 static void ssd1307fb_deferred_io(struct fb_info *info, 283 struct list_head *pagelist) 284 { 285 ssd1307fb_update_display(info->par); 286 } 287 288 static int ssd1307fb_init(struct ssd1307fb_par *par) 289 { 290 int ret; 291 u32 precharge, dclk, com_invdir, compins; 292 struct pwm_args pargs; 293 294 if (par->device_info->need_pwm) { 295 par->pwm = pwm_get(&par->client->dev, NULL); 296 if (IS_ERR(par->pwm)) { 297 dev_err(&par->client->dev, "Could not get PWM from device tree!\n"); 298 return PTR_ERR(par->pwm); 299 } 300 301 /* 302 * FIXME: pwm_apply_args() should be removed when switching to 303 * the atomic PWM API. 304 */ 305 pwm_apply_args(par->pwm); 306 307 pwm_get_args(par->pwm, &pargs); 308 309 par->pwm_period = pargs.period; 310 /* Enable the PWM */ 311 pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period); 312 pwm_enable(par->pwm); 313 314 dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n", 315 par->pwm->pwm, par->pwm_period); 316 }; 317 318 /* Set initial contrast */ 319 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST); 320 if (ret < 0) 321 return ret; 322 323 ret = ssd1307fb_write_cmd(par->client, par->contrast); 324 if (ret < 0) 325 return ret; 326 327 /* Set segment re-map */ 328 if (par->seg_remap) { 329 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON); 330 if (ret < 0) 331 return ret; 332 }; 333 334 /* Set COM direction */ 335 com_invdir = 0xc0 | (par->com_invdir & 0x1) << 3; 336 ret = ssd1307fb_write_cmd(par->client, com_invdir); 337 if (ret < 0) 338 return ret; 339 340 /* Set multiplex ratio value */ 341 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO); 342 if (ret < 0) 343 return ret; 344 345 ret = ssd1307fb_write_cmd(par->client, par->height - 1); 346 if (ret < 0) 347 return ret; 348 349 /* set display offset value */ 350 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET); 351 if (ret < 0) 352 return ret; 353 354 ret = ssd1307fb_write_cmd(par->client, par->com_offset); 355 if (ret < 0) 356 return ret; 357 358 /* Set clock frequency */ 359 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ); 360 if (ret < 0) 361 return ret; 362 363 dclk = ((par->dclk_div - 1) & 0xf) | (par->dclk_frq & 0xf) << 4; 364 ret = ssd1307fb_write_cmd(par->client, dclk); 365 if (ret < 0) 366 return ret; 367 368 /* Set precharge period in number of ticks from the internal clock */ 369 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD); 370 if (ret < 0) 371 return ret; 372 373 precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4; 374 ret = ssd1307fb_write_cmd(par->client, precharge); 375 if (ret < 0) 376 return ret; 377 378 /* Set COM pins configuration */ 379 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG); 380 if (ret < 0) 381 return ret; 382 383 compins = 0x02 | !(par->com_seq & 0x1) << 4 384 | (par->com_lrremap & 0x1) << 5; 385 ret = ssd1307fb_write_cmd(par->client, compins); 386 if (ret < 0) 387 return ret; 388 389 /* Set VCOMH */ 390 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH); 391 if (ret < 0) 392 return ret; 393 394 ret = ssd1307fb_write_cmd(par->client, par->vcomh); 395 if (ret < 0) 396 return ret; 397 398 /* Turn on the DC-DC Charge Pump */ 399 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP); 400 if (ret < 0) 401 return ret; 402 403 ret = ssd1307fb_write_cmd(par->client, 404 BIT(4) | (par->device_info->need_chargepump ? BIT(2) : 0)); 405 if (ret < 0) 406 return ret; 407 408 /* Switch to horizontal addressing mode */ 409 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE); 410 if (ret < 0) 411 return ret; 412 413 ret = ssd1307fb_write_cmd(par->client, 414 SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL); 415 if (ret < 0) 416 return ret; 417 418 /* Set column range */ 419 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE); 420 if (ret < 0) 421 return ret; 422 423 ret = ssd1307fb_write_cmd(par->client, 0x0); 424 if (ret < 0) 425 return ret; 426 427 ret = ssd1307fb_write_cmd(par->client, par->width - 1); 428 if (ret < 0) 429 return ret; 430 431 /* Set page range */ 432 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE); 433 if (ret < 0) 434 return ret; 435 436 ret = ssd1307fb_write_cmd(par->client, 0x0); 437 if (ret < 0) 438 return ret; 439 440 ret = ssd1307fb_write_cmd(par->client, 441 par->page_offset + (par->height / 8) - 1); 442 if (ret < 0) 443 return ret; 444 445 /* Clear the screen */ 446 ssd1307fb_update_display(par); 447 448 /* Turn on the display */ 449 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); 450 if (ret < 0) 451 return ret; 452 453 return 0; 454 } 455 456 static int ssd1307fb_update_bl(struct backlight_device *bdev) 457 { 458 struct ssd1307fb_par *par = bl_get_data(bdev); 459 int ret; 460 int brightness = bdev->props.brightness; 461 462 par->contrast = brightness; 463 464 ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST); 465 if (ret < 0) 466 return ret; 467 ret = ssd1307fb_write_cmd(par->client, par->contrast); 468 if (ret < 0) 469 return ret; 470 return 0; 471 } 472 473 static int ssd1307fb_get_brightness(struct backlight_device *bdev) 474 { 475 struct ssd1307fb_par *par = bl_get_data(bdev); 476 477 return par->contrast; 478 } 479 480 static int ssd1307fb_check_fb(struct backlight_device *bdev, 481 struct fb_info *info) 482 { 483 return (info->bl_dev == bdev); 484 } 485 486 static const struct backlight_ops ssd1307fb_bl_ops = { 487 .options = BL_CORE_SUSPENDRESUME, 488 .update_status = ssd1307fb_update_bl, 489 .get_brightness = ssd1307fb_get_brightness, 490 .check_fb = ssd1307fb_check_fb, 491 }; 492 493 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = { 494 .default_vcomh = 0x34, 495 .default_dclk_div = 1, 496 .default_dclk_frq = 7, 497 }; 498 499 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = { 500 .default_vcomh = 0x20, 501 .default_dclk_div = 1, 502 .default_dclk_frq = 8, 503 .need_chargepump = 1, 504 }; 505 506 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = { 507 .default_vcomh = 0x20, 508 .default_dclk_div = 2, 509 .default_dclk_frq = 12, 510 .need_pwm = 1, 511 }; 512 513 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1309_deviceinfo = { 514 .default_vcomh = 0x34, 515 .default_dclk_div = 1, 516 .default_dclk_frq = 10, 517 }; 518 519 static const struct of_device_id ssd1307fb_of_match[] = { 520 { 521 .compatible = "solomon,ssd1305fb-i2c", 522 .data = (void *)&ssd1307fb_ssd1305_deviceinfo, 523 }, 524 { 525 .compatible = "solomon,ssd1306fb-i2c", 526 .data = (void *)&ssd1307fb_ssd1306_deviceinfo, 527 }, 528 { 529 .compatible = "solomon,ssd1307fb-i2c", 530 .data = (void *)&ssd1307fb_ssd1307_deviceinfo, 531 }, 532 { 533 .compatible = "solomon,ssd1309fb-i2c", 534 .data = (void *)&ssd1307fb_ssd1309_deviceinfo, 535 }, 536 {}, 537 }; 538 MODULE_DEVICE_TABLE(of, ssd1307fb_of_match); 539 540 static int ssd1307fb_probe(struct i2c_client *client, 541 const struct i2c_device_id *id) 542 { 543 struct backlight_device *bl; 544 char bl_name[12]; 545 struct fb_info *info; 546 struct device_node *node = client->dev.of_node; 547 struct fb_deferred_io *ssd1307fb_defio; 548 u32 vmem_size; 549 struct ssd1307fb_par *par; 550 u8 *vmem; 551 int ret; 552 553 if (!node) { 554 dev_err(&client->dev, "No device tree data found!\n"); 555 return -EINVAL; 556 } 557 558 info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev); 559 if (!info) { 560 dev_err(&client->dev, "Couldn't allocate framebuffer.\n"); 561 return -ENOMEM; 562 } 563 564 par = info->par; 565 par->info = info; 566 par->client = client; 567 568 par->device_info = of_device_get_match_data(&client->dev); 569 570 par->reset = devm_gpiod_get_optional(&client->dev, "reset", 571 GPIOD_OUT_LOW); 572 if (IS_ERR(par->reset)) { 573 dev_err(&client->dev, "failed to get reset gpio: %ld\n", 574 PTR_ERR(par->reset)); 575 ret = PTR_ERR(par->reset); 576 goto fb_alloc_error; 577 } 578 579 par->vbat_reg = devm_regulator_get_optional(&client->dev, "vbat"); 580 if (IS_ERR(par->vbat_reg)) { 581 dev_err(&client->dev, "failed to get VBAT regulator: %ld\n", 582 PTR_ERR(par->vbat_reg)); 583 ret = PTR_ERR(par->vbat_reg); 584 goto fb_alloc_error; 585 } 586 587 if (of_property_read_u32(node, "solomon,width", &par->width)) 588 par->width = 96; 589 590 if (of_property_read_u32(node, "solomon,height", &par->height)) 591 par->height = 16; 592 593 if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset)) 594 par->page_offset = 1; 595 596 if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset)) 597 par->com_offset = 0; 598 599 if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1)) 600 par->prechargep1 = 2; 601 602 if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2)) 603 par->prechargep2 = 2; 604 605 par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap"); 606 par->com_seq = of_property_read_bool(node, "solomon,com-seq"); 607 par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap"); 608 par->com_invdir = of_property_read_bool(node, "solomon,com-invdir"); 609 610 par->contrast = 127; 611 par->vcomh = par->device_info->default_vcomh; 612 613 /* Setup display timing */ 614 par->dclk_div = par->device_info->default_dclk_div; 615 par->dclk_frq = par->device_info->default_dclk_frq; 616 617 vmem_size = par->width * par->height / 8; 618 619 vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 620 get_order(vmem_size)); 621 if (!vmem) { 622 dev_err(&client->dev, "Couldn't allocate graphical memory.\n"); 623 ret = -ENOMEM; 624 goto fb_alloc_error; 625 } 626 627 ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(struct fb_deferred_io), GFP_KERNEL); 628 if (!ssd1307fb_defio) { 629 dev_err(&client->dev, "Couldn't allocate deferred io.\n"); 630 ret = -ENOMEM; 631 goto fb_alloc_error; 632 } 633 634 ssd1307fb_defio->delay = HZ / refreshrate; 635 ssd1307fb_defio->deferred_io = ssd1307fb_deferred_io; 636 637 info->fbops = &ssd1307fb_ops; 638 info->fix = ssd1307fb_fix; 639 info->fix.line_length = par->width / 8; 640 info->fbdefio = ssd1307fb_defio; 641 642 info->var = ssd1307fb_var; 643 info->var.xres = par->width; 644 info->var.xres_virtual = par->width; 645 info->var.yres = par->height; 646 info->var.yres_virtual = par->height; 647 648 info->var.red.length = 1; 649 info->var.red.offset = 0; 650 info->var.green.length = 1; 651 info->var.green.offset = 0; 652 info->var.blue.length = 1; 653 info->var.blue.offset = 0; 654 655 info->screen_base = (u8 __force __iomem *)vmem; 656 info->fix.smem_start = __pa(vmem); 657 info->fix.smem_len = vmem_size; 658 659 fb_deferred_io_init(info); 660 661 i2c_set_clientdata(client, info); 662 663 if (par->reset) { 664 /* Reset the screen */ 665 gpiod_set_value(par->reset, 0); 666 udelay(4); 667 gpiod_set_value(par->reset, 1); 668 udelay(4); 669 } 670 671 ret = regulator_enable(par->vbat_reg); 672 if (ret) { 673 dev_err(&client->dev, "failed to enable VBAT: %d\n", ret); 674 goto reset_oled_error; 675 } 676 677 ret = ssd1307fb_init(par); 678 if (ret) 679 goto regulator_enable_error; 680 681 ret = register_framebuffer(info); 682 if (ret) { 683 dev_err(&client->dev, "Couldn't register the framebuffer\n"); 684 goto panel_init_error; 685 } 686 687 snprintf(bl_name, sizeof(bl_name), "ssd1307fb%d", info->node); 688 bl = backlight_device_register(bl_name, &client->dev, par, 689 &ssd1307fb_bl_ops, NULL); 690 if (IS_ERR(bl)) { 691 ret = PTR_ERR(bl); 692 dev_err(&client->dev, "unable to register backlight device: %d\n", 693 ret); 694 goto bl_init_error; 695 } 696 697 bl->props.brightness = par->contrast; 698 bl->props.max_brightness = MAX_CONTRAST; 699 info->bl_dev = bl; 700 701 dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size); 702 703 return 0; 704 705 bl_init_error: 706 unregister_framebuffer(info); 707 panel_init_error: 708 if (par->device_info->need_pwm) { 709 pwm_disable(par->pwm); 710 pwm_put(par->pwm); 711 }; 712 regulator_enable_error: 713 regulator_disable(par->vbat_reg); 714 reset_oled_error: 715 fb_deferred_io_cleanup(info); 716 fb_alloc_error: 717 framebuffer_release(info); 718 return ret; 719 } 720 721 static int ssd1307fb_remove(struct i2c_client *client) 722 { 723 struct fb_info *info = i2c_get_clientdata(client); 724 struct ssd1307fb_par *par = info->par; 725 726 ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF); 727 728 backlight_device_unregister(info->bl_dev); 729 730 unregister_framebuffer(info); 731 if (par->device_info->need_pwm) { 732 pwm_disable(par->pwm); 733 pwm_put(par->pwm); 734 }; 735 fb_deferred_io_cleanup(info); 736 __free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len)); 737 framebuffer_release(info); 738 739 return 0; 740 } 741 742 static const struct i2c_device_id ssd1307fb_i2c_id[] = { 743 { "ssd1305fb", 0 }, 744 { "ssd1306fb", 0 }, 745 { "ssd1307fb", 0 }, 746 { "ssd1309fb", 0 }, 747 { } 748 }; 749 MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id); 750 751 static struct i2c_driver ssd1307fb_driver = { 752 .probe = ssd1307fb_probe, 753 .remove = ssd1307fb_remove, 754 .id_table = ssd1307fb_i2c_id, 755 .driver = { 756 .name = "ssd1307fb", 757 .of_match_table = ssd1307fb_of_match, 758 }, 759 }; 760 761 module_i2c_driver(ssd1307fb_driver); 762 763 MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controller"); 764 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 765 MODULE_LICENSE("GPL"); 766