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 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 518 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 519 .width_mm = 77, 520 .height_mm = 46, 521 }; 522 523 static int acx565akm_get_modes(struct drm_panel *panel, 524 struct drm_connector *connector) 525 { 526 struct drm_display_mode *mode; 527 528 mode = drm_mode_duplicate(connector->dev, &acx565akm_mode); 529 if (!mode) 530 return -ENOMEM; 531 532 drm_mode_set_name(mode); 533 drm_mode_probed_add(connector, mode); 534 535 connector->display_info.width_mm = acx565akm_mode.width_mm; 536 connector->display_info.height_mm = acx565akm_mode.height_mm; 537 connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH 538 | DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE 539 | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE; 540 541 return 1; 542 } 543 544 static const struct drm_panel_funcs acx565akm_funcs = { 545 .disable = acx565akm_disable, 546 .enable = acx565akm_enable, 547 .get_modes = acx565akm_get_modes, 548 }; 549 550 /* ----------------------------------------------------------------------------- 551 * Probe, Detect and Remove 552 */ 553 554 static int acx565akm_detect(struct acx565akm_panel *lcd) 555 { 556 __be32 value; 557 u32 status; 558 int ret = 0; 559 560 /* 561 * After being taken out of reset the panel needs 5ms before the first 562 * command can be sent. 563 */ 564 gpiod_set_value(lcd->reset_gpio, 1); 565 usleep_range(5000, 10000); 566 567 acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_STATUS, (u8 *)&value, 4); 568 status = __be32_to_cpu(value); 569 lcd->enabled = (status & (1 << 17)) && (status & (1 << 10)); 570 571 dev_dbg(&lcd->spi->dev, 572 "LCD panel %s by bootloader (status 0x%04x)\n", 573 lcd->enabled ? "enabled" : "disabled ", status); 574 575 acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_ID, lcd->display_id, 3); 576 dev_dbg(&lcd->spi->dev, "MIPI display ID: %02x%02x%02x\n", 577 lcd->display_id[0], lcd->display_id[1], lcd->display_id[2]); 578 579 switch (lcd->display_id[0]) { 580 case 0x10: 581 lcd->model = MIPID_VER_ACX565AKM; 582 lcd->name = "acx565akm"; 583 lcd->has_bc = 1; 584 lcd->has_cabc = 1; 585 break; 586 case 0x29: 587 lcd->model = MIPID_VER_L4F00311; 588 lcd->name = "l4f00311"; 589 break; 590 case 0x45: 591 lcd->model = MIPID_VER_LPH8923; 592 lcd->name = "lph8923"; 593 break; 594 case 0x83: 595 lcd->model = MIPID_VER_LS041Y3; 596 lcd->name = "ls041y3"; 597 break; 598 default: 599 lcd->name = "unknown"; 600 dev_err(&lcd->spi->dev, "unknown display ID\n"); 601 ret = -ENODEV; 602 goto done; 603 } 604 605 lcd->revision = lcd->display_id[1]; 606 607 dev_info(&lcd->spi->dev, "%s rev %02x panel detected\n", 608 lcd->name, lcd->revision); 609 610 done: 611 if (!lcd->enabled) 612 gpiod_set_value(lcd->reset_gpio, 0); 613 614 return ret; 615 } 616 617 static int acx565akm_probe(struct spi_device *spi) 618 { 619 struct acx565akm_panel *lcd; 620 int ret; 621 622 lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL); 623 if (!lcd) 624 return -ENOMEM; 625 626 spi_set_drvdata(spi, lcd); 627 spi->mode = SPI_MODE_3; 628 629 lcd->spi = spi; 630 mutex_init(&lcd->mutex); 631 632 lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW); 633 if (IS_ERR(lcd->reset_gpio)) { 634 dev_err(&spi->dev, "failed to get reset GPIO\n"); 635 return PTR_ERR(lcd->reset_gpio); 636 } 637 638 ret = acx565akm_detect(lcd); 639 if (ret < 0) { 640 dev_err(&spi->dev, "panel detection failed\n"); 641 return ret; 642 } 643 644 if (lcd->has_bc) { 645 ret = acx565akm_backlight_init(lcd); 646 if (ret < 0) 647 return ret; 648 } 649 650 drm_panel_init(&lcd->panel, &lcd->spi->dev, &acx565akm_funcs, 651 DRM_MODE_CONNECTOR_DPI); 652 653 ret = drm_panel_add(&lcd->panel); 654 if (ret < 0) { 655 if (lcd->has_bc) 656 acx565akm_backlight_cleanup(lcd); 657 return ret; 658 } 659 660 return 0; 661 } 662 663 static int acx565akm_remove(struct spi_device *spi) 664 { 665 struct acx565akm_panel *lcd = spi_get_drvdata(spi); 666 667 drm_panel_remove(&lcd->panel); 668 669 if (lcd->has_bc) 670 acx565akm_backlight_cleanup(lcd); 671 672 drm_panel_disable(&lcd->panel); 673 drm_panel_unprepare(&lcd->panel); 674 675 return 0; 676 } 677 678 static const struct of_device_id acx565akm_of_match[] = { 679 { .compatible = "sony,acx565akm", }, 680 { /* sentinel */ }, 681 }; 682 683 MODULE_DEVICE_TABLE(of, acx565akm_of_match); 684 685 static const struct spi_device_id acx565akm_ids[] = { 686 { "acx565akm", 0 }, 687 { /* sentinel */ } 688 }; 689 690 MODULE_DEVICE_TABLE(spi, acx565akm_ids); 691 692 static struct spi_driver acx565akm_driver = { 693 .probe = acx565akm_probe, 694 .remove = acx565akm_remove, 695 .id_table = acx565akm_ids, 696 .driver = { 697 .name = "panel-sony-acx565akm", 698 .of_match_table = acx565akm_of_match, 699 }, 700 }; 701 702 module_spi_driver(acx565akm_driver); 703 704 MODULE_AUTHOR("Nokia Corporation"); 705 MODULE_DESCRIPTION("Sony ACX565AKM LCD Panel Driver"); 706 MODULE_LICENSE("GPL"); 707