1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Sony ACX565AKM LCD Panel driver 4 * 5 * Copyright (C) 2019 Texas Instruments Incorporated 6 * 7 * Based on the omapdrm-specific panel-sony-acx565akm driver 8 * 9 * Copyright (C) 2010 Nokia Corporation 10 * Author: Imre Deak <imre.deak@nokia.com> 11 */ 12 13 /* 14 * TODO (to be addressed with hardware access to test the changes): 15 * 16 * - Update backlight support to use backlight_update_status() etc. 17 * - Use prepare/unprepare for the basic power on/off of the backligt 18 */ 19 20 #include <linux/backlight.h> 21 #include <linux/delay.h> 22 #include <linux/gpio/consumer.h> 23 #include <linux/jiffies.h> 24 #include <linux/module.h> 25 #include <linux/mutex.h> 26 #include <linux/sched.h> 27 #include <linux/spi/spi.h> 28 #include <video/mipi_display.h> 29 30 #include <drm/drm_connector.h> 31 #include <drm/drm_modes.h> 32 #include <drm/drm_panel.h> 33 34 #define CTRL_DISP_BRIGHTNESS_CTRL_ON BIT(5) 35 #define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON BIT(4) 36 #define CTRL_DISP_BACKLIGHT_ON BIT(2) 37 #define CTRL_DISP_AUTO_BRIGHTNESS_ON BIT(1) 38 39 #define MIPID_CMD_WRITE_CABC 0x55 40 #define MIPID_CMD_READ_CABC 0x56 41 42 #define MIPID_VER_LPH8923 3 43 #define MIPID_VER_LS041Y3 4 44 #define MIPID_VER_L4F00311 8 45 #define MIPID_VER_ACX565AKM 9 46 47 struct acx565akm_panel { 48 struct drm_panel panel; 49 50 struct spi_device *spi; 51 struct gpio_desc *reset_gpio; 52 struct backlight_device *backlight; 53 54 struct mutex mutex; 55 56 const char *name; 57 u8 display_id[3]; 58 int model; 59 int revision; 60 bool has_bc; 61 bool has_cabc; 62 63 bool enabled; 64 unsigned int cabc_mode; 65 /* 66 * Next value of jiffies when we can issue the next sleep in/out 67 * command. 68 */ 69 unsigned long hw_guard_end; 70 unsigned long hw_guard_wait; /* max guard time in jiffies */ 71 }; 72 73 #define to_acx565akm_device(p) container_of(p, struct acx565akm_panel, panel) 74 75 static void acx565akm_transfer(struct acx565akm_panel *lcd, int cmd, 76 const u8 *wbuf, int wlen, u8 *rbuf, int rlen) 77 { 78 struct spi_message m; 79 struct spi_transfer *x, xfer[5]; 80 int ret; 81 82 spi_message_init(&m); 83 84 memset(xfer, 0, sizeof(xfer)); 85 x = &xfer[0]; 86 87 cmd &= 0xff; 88 x->tx_buf = &cmd; 89 x->bits_per_word = 9; 90 x->len = 2; 91 92 if (rlen > 1 && wlen == 0) { 93 /* 94 * Between the command and the response data there is a 95 * dummy clock cycle. Add an extra bit after the command 96 * word to account for this. 97 */ 98 x->bits_per_word = 10; 99 cmd <<= 1; 100 } 101 spi_message_add_tail(x, &m); 102 103 if (wlen) { 104 x++; 105 x->tx_buf = wbuf; 106 x->len = wlen; 107 x->bits_per_word = 9; 108 spi_message_add_tail(x, &m); 109 } 110 111 if (rlen) { 112 x++; 113 x->rx_buf = rbuf; 114 x->len = rlen; 115 spi_message_add_tail(x, &m); 116 } 117 118 ret = spi_sync(lcd->spi, &m); 119 if (ret < 0) 120 dev_dbg(&lcd->spi->dev, "spi_sync %d\n", ret); 121 } 122 123 static inline void acx565akm_cmd(struct acx565akm_panel *lcd, int cmd) 124 { 125 acx565akm_transfer(lcd, cmd, NULL, 0, NULL, 0); 126 } 127 128 static inline void acx565akm_write(struct acx565akm_panel *lcd, 129 int reg, const u8 *buf, int len) 130 { 131 acx565akm_transfer(lcd, reg, buf, len, NULL, 0); 132 } 133 134 static inline void acx565akm_read(struct acx565akm_panel *lcd, 135 int reg, u8 *buf, int len) 136 { 137 acx565akm_transfer(lcd, reg, NULL, 0, buf, len); 138 } 139 140 /* ----------------------------------------------------------------------------- 141 * Auto Brightness Control Via sysfs 142 */ 143 144 static unsigned int acx565akm_get_cabc_mode(struct acx565akm_panel *lcd) 145 { 146 return lcd->cabc_mode; 147 } 148 149 static void acx565akm_set_cabc_mode(struct acx565akm_panel *lcd, 150 unsigned int mode) 151 { 152 u16 cabc_ctrl; 153 154 lcd->cabc_mode = mode; 155 if (!lcd->enabled) 156 return; 157 cabc_ctrl = 0; 158 acx565akm_read(lcd, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1); 159 cabc_ctrl &= ~3; 160 cabc_ctrl |= (1 << 8) | (mode & 3); 161 acx565akm_write(lcd, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2); 162 } 163 164 static unsigned int acx565akm_get_hw_cabc_mode(struct acx565akm_panel *lcd) 165 { 166 u8 cabc_ctrl; 167 168 acx565akm_read(lcd, MIPID_CMD_READ_CABC, &cabc_ctrl, 1); 169 return cabc_ctrl & 3; 170 } 171 172 static const char * const acx565akm_cabc_modes[] = { 173 "off", /* always used when CABC is not supported */ 174 "ui", 175 "still-image", 176 "moving-image", 177 }; 178 179 static ssize_t cabc_mode_show(struct device *dev, 180 struct device_attribute *attr, 181 char *buf) 182 { 183 struct acx565akm_panel *lcd = dev_get_drvdata(dev); 184 const char *mode_str; 185 int mode; 186 187 if (!lcd->has_cabc) 188 mode = 0; 189 else 190 mode = acx565akm_get_cabc_mode(lcd); 191 192 mode_str = "unknown"; 193 if (mode >= 0 && mode < ARRAY_SIZE(acx565akm_cabc_modes)) 194 mode_str = acx565akm_cabc_modes[mode]; 195 196 return sprintf(buf, "%s\n", mode_str); 197 } 198 199 static ssize_t cabc_mode_store(struct device *dev, 200 struct device_attribute *attr, 201 const char *buf, size_t count) 202 { 203 struct acx565akm_panel *lcd = dev_get_drvdata(dev); 204 unsigned int i; 205 206 for (i = 0; i < ARRAY_SIZE(acx565akm_cabc_modes); i++) { 207 const char *mode_str = acx565akm_cabc_modes[i]; 208 int cmp_len = strlen(mode_str); 209 210 if (count > 0 && buf[count - 1] == '\n') 211 count--; 212 if (count != cmp_len) 213 continue; 214 215 if (strncmp(buf, mode_str, cmp_len) == 0) 216 break; 217 } 218 219 if (i == ARRAY_SIZE(acx565akm_cabc_modes)) 220 return -EINVAL; 221 222 if (!lcd->has_cabc && i != 0) 223 return -EINVAL; 224 225 mutex_lock(&lcd->mutex); 226 acx565akm_set_cabc_mode(lcd, i); 227 mutex_unlock(&lcd->mutex); 228 229 return count; 230 } 231 232 static ssize_t cabc_available_modes_show(struct device *dev, 233 struct device_attribute *attr, 234 char *buf) 235 { 236 struct acx565akm_panel *lcd = dev_get_drvdata(dev); 237 unsigned int i; 238 size_t len = 0; 239 240 if (!lcd->has_cabc) 241 return sprintf(buf, "%s\n", acx565akm_cabc_modes[0]); 242 243 for (i = 0; i < ARRAY_SIZE(acx565akm_cabc_modes); i++) 244 len += sprintf(&buf[len], "%s%s", i ? " " : "", 245 acx565akm_cabc_modes[i]); 246 247 buf[len++] = '\n'; 248 249 return len; 250 } 251 252 static DEVICE_ATTR_RW(cabc_mode); 253 static DEVICE_ATTR_RO(cabc_available_modes); 254 255 static struct attribute *acx565akm_cabc_attrs[] = { 256 &dev_attr_cabc_mode.attr, 257 &dev_attr_cabc_available_modes.attr, 258 NULL, 259 }; 260 261 static const struct attribute_group acx565akm_cabc_attr_group = { 262 .attrs = acx565akm_cabc_attrs, 263 }; 264 265 /* ----------------------------------------------------------------------------- 266 * Backlight Device 267 */ 268 269 static int acx565akm_get_actual_brightness(struct acx565akm_panel *lcd) 270 { 271 u8 bv; 272 273 acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_BRIGHTNESS, &bv, 1); 274 275 return bv; 276 } 277 278 static void acx565akm_set_brightness(struct acx565akm_panel *lcd, int level) 279 { 280 u16 ctrl; 281 int bv; 282 283 bv = level | (1 << 8); 284 acx565akm_write(lcd, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, (u8 *)&bv, 2); 285 286 acx565akm_read(lcd, MIPI_DCS_GET_CONTROL_DISPLAY, (u8 *)&ctrl, 1); 287 if (level) 288 ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON | 289 CTRL_DISP_BACKLIGHT_ON; 290 else 291 ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON | 292 CTRL_DISP_BACKLIGHT_ON); 293 294 ctrl |= 1 << 8; 295 acx565akm_write(lcd, MIPI_DCS_WRITE_CONTROL_DISPLAY, (u8 *)&ctrl, 2); 296 } 297 298 static int acx565akm_bl_update_status_locked(struct backlight_device *dev) 299 { 300 struct acx565akm_panel *lcd = dev_get_drvdata(&dev->dev); 301 int level; 302 303 if (dev->props.fb_blank == FB_BLANK_UNBLANK && 304 dev->props.power == FB_BLANK_UNBLANK) 305 level = dev->props.brightness; 306 else 307 level = 0; 308 309 acx565akm_set_brightness(lcd, level); 310 311 return 0; 312 } 313 314 static int acx565akm_bl_update_status(struct backlight_device *dev) 315 { 316 struct acx565akm_panel *lcd = dev_get_drvdata(&dev->dev); 317 int ret; 318 319 mutex_lock(&lcd->mutex); 320 ret = acx565akm_bl_update_status_locked(dev); 321 mutex_unlock(&lcd->mutex); 322 323 return ret; 324 } 325 326 static int acx565akm_bl_get_intensity(struct backlight_device *dev) 327 { 328 struct acx565akm_panel *lcd = dev_get_drvdata(&dev->dev); 329 unsigned int intensity; 330 331 mutex_lock(&lcd->mutex); 332 333 if (dev->props.fb_blank == FB_BLANK_UNBLANK && 334 dev->props.power == FB_BLANK_UNBLANK) 335 intensity = acx565akm_get_actual_brightness(lcd); 336 else 337 intensity = 0; 338 339 mutex_unlock(&lcd->mutex); 340 341 return intensity; 342 } 343 344 static const struct backlight_ops acx565akm_bl_ops = { 345 .get_brightness = acx565akm_bl_get_intensity, 346 .update_status = acx565akm_bl_update_status, 347 }; 348 349 static int acx565akm_backlight_init(struct acx565akm_panel *lcd) 350 { 351 struct backlight_properties props = { 352 .fb_blank = FB_BLANK_UNBLANK, 353 .power = FB_BLANK_UNBLANK, 354 .type = BACKLIGHT_RAW, 355 }; 356 int ret; 357 358 lcd->backlight = backlight_device_register(lcd->name, &lcd->spi->dev, 359 lcd, &acx565akm_bl_ops, 360 &props); 361 if (IS_ERR(lcd->backlight)) { 362 ret = PTR_ERR(lcd->backlight); 363 lcd->backlight = NULL; 364 return ret; 365 } 366 367 if (lcd->has_cabc) { 368 ret = sysfs_create_group(&lcd->backlight->dev.kobj, 369 &acx565akm_cabc_attr_group); 370 if (ret < 0) { 371 dev_err(&lcd->spi->dev, 372 "%s failed to create sysfs files\n", __func__); 373 backlight_device_unregister(lcd->backlight); 374 return ret; 375 } 376 377 lcd->cabc_mode = acx565akm_get_hw_cabc_mode(lcd); 378 } 379 380 lcd->backlight->props.max_brightness = 255; 381 lcd->backlight->props.brightness = acx565akm_get_actual_brightness(lcd); 382 383 acx565akm_bl_update_status_locked(lcd->backlight); 384 385 return 0; 386 } 387 388 static void acx565akm_backlight_cleanup(struct acx565akm_panel *lcd) 389 { 390 if (lcd->has_cabc) 391 sysfs_remove_group(&lcd->backlight->dev.kobj, 392 &acx565akm_cabc_attr_group); 393 394 backlight_device_unregister(lcd->backlight); 395 } 396 397 /* ----------------------------------------------------------------------------- 398 * DRM Bridge Operations 399 */ 400 401 static void acx565akm_set_sleep_mode(struct acx565akm_panel *lcd, int on) 402 { 403 int cmd = on ? MIPI_DCS_ENTER_SLEEP_MODE : MIPI_DCS_EXIT_SLEEP_MODE; 404 unsigned long wait; 405 406 /* 407 * We have to keep 120msec between sleep in/out commands. 408 * (8.2.15, 8.2.16). 409 */ 410 wait = lcd->hw_guard_end - jiffies; 411 if ((long)wait > 0 && wait <= lcd->hw_guard_wait) { 412 set_current_state(TASK_UNINTERRUPTIBLE); 413 schedule_timeout(wait); 414 } 415 416 acx565akm_cmd(lcd, cmd); 417 418 lcd->hw_guard_wait = msecs_to_jiffies(120); 419 lcd->hw_guard_end = jiffies + lcd->hw_guard_wait; 420 } 421 422 static void acx565akm_set_display_state(struct acx565akm_panel *lcd, 423 int enabled) 424 { 425 int cmd = enabled ? MIPI_DCS_SET_DISPLAY_ON : MIPI_DCS_SET_DISPLAY_OFF; 426 427 acx565akm_cmd(lcd, cmd); 428 } 429 430 static int acx565akm_power_on(struct acx565akm_panel *lcd) 431 { 432 /*FIXME tweak me */ 433 msleep(50); 434 435 gpiod_set_value(lcd->reset_gpio, 1); 436 437 if (lcd->enabled) { 438 dev_dbg(&lcd->spi->dev, "panel already enabled\n"); 439 return 0; 440 } 441 442 /* 443 * We have to meet all the following delay requirements: 444 * 1. tRW: reset pulse width 10usec (7.12.1) 445 * 2. tRT: reset cancel time 5msec (7.12.1) 446 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst 447 * case (7.6.2) 448 * 4. 120msec before the sleep out command (7.12.1) 449 */ 450 msleep(120); 451 452 acx565akm_set_sleep_mode(lcd, 0); 453 lcd->enabled = true; 454 455 /* 5msec between sleep out and the next command. (8.2.16) */ 456 usleep_range(5000, 10000); 457 acx565akm_set_display_state(lcd, 1); 458 acx565akm_set_cabc_mode(lcd, lcd->cabc_mode); 459 460 return acx565akm_bl_update_status_locked(lcd->backlight); 461 } 462 463 static void acx565akm_power_off(struct acx565akm_panel *lcd) 464 { 465 if (!lcd->enabled) 466 return; 467 468 acx565akm_set_display_state(lcd, 0); 469 acx565akm_set_sleep_mode(lcd, 1); 470 lcd->enabled = false; 471 /* 472 * We have to provide PCLK,HS,VS signals for 2 frames (worst case 473 * ~50msec) after sending the sleep in command and asserting the 474 * reset signal. We probably could assert the reset w/o the delay 475 * but we still delay to avoid possible artifacts. (7.6.1) 476 */ 477 msleep(50); 478 479 gpiod_set_value(lcd->reset_gpio, 0); 480 481 /* FIXME need to tweak this delay */ 482 msleep(100); 483 } 484 485 static int acx565akm_disable(struct drm_panel *panel) 486 { 487 struct acx565akm_panel *lcd = to_acx565akm_device(panel); 488 489 mutex_lock(&lcd->mutex); 490 acx565akm_power_off(lcd); 491 mutex_unlock(&lcd->mutex); 492 493 return 0; 494 } 495 496 static int acx565akm_enable(struct drm_panel *panel) 497 { 498 struct acx565akm_panel *lcd = to_acx565akm_device(panel); 499 500 mutex_lock(&lcd->mutex); 501 acx565akm_power_on(lcd); 502 mutex_unlock(&lcd->mutex); 503 504 return 0; 505 } 506 507 static const struct drm_display_mode acx565akm_mode = { 508 .clock = 24000, 509 .hdisplay = 800, 510 .hsync_start = 800 + 28, 511 .hsync_end = 800 + 28 + 4, 512 .htotal = 800 + 28 + 4 + 24, 513 .vdisplay = 480, 514 .vsync_start = 480 + 3, 515 .vsync_end = 480 + 3 + 3, 516 .vtotal = 480 + 3 + 3 + 4, 517 .vrefresh = 57, 518 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 519 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 520 .width_mm = 77, 521 .height_mm = 46, 522 }; 523 524 static int acx565akm_get_modes(struct drm_panel *panel, 525 struct drm_connector *connector) 526 { 527 struct drm_display_mode *mode; 528 529 mode = drm_mode_duplicate(connector->dev, &acx565akm_mode); 530 if (!mode) 531 return -ENOMEM; 532 533 drm_mode_set_name(mode); 534 drm_mode_probed_add(connector, mode); 535 536 connector->display_info.width_mm = acx565akm_mode.width_mm; 537 connector->display_info.height_mm = acx565akm_mode.height_mm; 538 connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH 539 | DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE 540 | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE; 541 542 return 1; 543 } 544 545 static const struct drm_panel_funcs acx565akm_funcs = { 546 .disable = acx565akm_disable, 547 .enable = acx565akm_enable, 548 .get_modes = acx565akm_get_modes, 549 }; 550 551 /* ----------------------------------------------------------------------------- 552 * Probe, Detect and Remove 553 */ 554 555 static int acx565akm_detect(struct acx565akm_panel *lcd) 556 { 557 __be32 value; 558 u32 status; 559 int ret = 0; 560 561 /* 562 * After being taken out of reset the panel needs 5ms before the first 563 * command can be sent. 564 */ 565 gpiod_set_value(lcd->reset_gpio, 1); 566 usleep_range(5000, 10000); 567 568 acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_STATUS, (u8 *)&value, 4); 569 status = __be32_to_cpu(value); 570 lcd->enabled = (status & (1 << 17)) && (status & (1 << 10)); 571 572 dev_dbg(&lcd->spi->dev, 573 "LCD panel %s by bootloader (status 0x%04x)\n", 574 lcd->enabled ? "enabled" : "disabled ", status); 575 576 acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_ID, lcd->display_id, 3); 577 dev_dbg(&lcd->spi->dev, "MIPI display ID: %02x%02x%02x\n", 578 lcd->display_id[0], lcd->display_id[1], lcd->display_id[2]); 579 580 switch (lcd->display_id[0]) { 581 case 0x10: 582 lcd->model = MIPID_VER_ACX565AKM; 583 lcd->name = "acx565akm"; 584 lcd->has_bc = 1; 585 lcd->has_cabc = 1; 586 break; 587 case 0x29: 588 lcd->model = MIPID_VER_L4F00311; 589 lcd->name = "l4f00311"; 590 break; 591 case 0x45: 592 lcd->model = MIPID_VER_LPH8923; 593 lcd->name = "lph8923"; 594 break; 595 case 0x83: 596 lcd->model = MIPID_VER_LS041Y3; 597 lcd->name = "ls041y3"; 598 break; 599 default: 600 lcd->name = "unknown"; 601 dev_err(&lcd->spi->dev, "unknown display ID\n"); 602 ret = -ENODEV; 603 goto done; 604 } 605 606 lcd->revision = lcd->display_id[1]; 607 608 dev_info(&lcd->spi->dev, "%s rev %02x panel detected\n", 609 lcd->name, lcd->revision); 610 611 done: 612 if (!lcd->enabled) 613 gpiod_set_value(lcd->reset_gpio, 0); 614 615 return ret; 616 } 617 618 static int acx565akm_probe(struct spi_device *spi) 619 { 620 struct acx565akm_panel *lcd; 621 int ret; 622 623 lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL); 624 if (!lcd) 625 return -ENOMEM; 626 627 spi_set_drvdata(spi, lcd); 628 spi->mode = SPI_MODE_3; 629 630 lcd->spi = spi; 631 mutex_init(&lcd->mutex); 632 633 lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW); 634 if (IS_ERR(lcd->reset_gpio)) { 635 dev_err(&spi->dev, "failed to get reset GPIO\n"); 636 return PTR_ERR(lcd->reset_gpio); 637 } 638 639 ret = acx565akm_detect(lcd); 640 if (ret < 0) { 641 dev_err(&spi->dev, "panel detection failed\n"); 642 return ret; 643 } 644 645 if (lcd->has_bc) { 646 ret = acx565akm_backlight_init(lcd); 647 if (ret < 0) 648 return ret; 649 } 650 651 drm_panel_init(&lcd->panel, &lcd->spi->dev, &acx565akm_funcs, 652 DRM_MODE_CONNECTOR_DPI); 653 654 ret = drm_panel_add(&lcd->panel); 655 if (ret < 0) { 656 if (lcd->has_bc) 657 acx565akm_backlight_cleanup(lcd); 658 return ret; 659 } 660 661 return 0; 662 } 663 664 static int acx565akm_remove(struct spi_device *spi) 665 { 666 struct acx565akm_panel *lcd = spi_get_drvdata(spi); 667 668 drm_panel_remove(&lcd->panel); 669 670 if (lcd->has_bc) 671 acx565akm_backlight_cleanup(lcd); 672 673 drm_panel_disable(&lcd->panel); 674 drm_panel_unprepare(&lcd->panel); 675 676 return 0; 677 } 678 679 static const struct of_device_id acx565akm_of_match[] = { 680 { .compatible = "sony,acx565akm", }, 681 { /* sentinel */ }, 682 }; 683 684 MODULE_DEVICE_TABLE(of, acx565akm_of_match); 685 686 static const struct spi_device_id acx565akm_ids[] = { 687 { "acx565akm", 0 }, 688 { /* sentinel */ } 689 }; 690 691 MODULE_DEVICE_TABLE(spi, acx565akm_ids); 692 693 static struct spi_driver acx565akm_driver = { 694 .probe = acx565akm_probe, 695 .remove = acx565akm_remove, 696 .id_table = acx565akm_ids, 697 .driver = { 698 .name = "panel-sony-acx565akm", 699 .of_match_table = acx565akm_of_match, 700 }, 701 }; 702 703 module_spi_driver(acx565akm_driver); 704 705 MODULE_AUTHOR("Nokia Corporation"); 706 MODULE_DESCRIPTION("Sony ACX565AKM LCD Panel Driver"); 707 MODULE_LICENSE("GPL"); 708