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 = backlight_get_brightness(dev); 302 303 acx565akm_set_brightness(lcd, level); 304 305 return 0; 306 } 307 308 static int acx565akm_bl_update_status(struct backlight_device *dev) 309 { 310 struct acx565akm_panel *lcd = dev_get_drvdata(&dev->dev); 311 int ret; 312 313 mutex_lock(&lcd->mutex); 314 ret = acx565akm_bl_update_status_locked(dev); 315 mutex_unlock(&lcd->mutex); 316 317 return ret; 318 } 319 320 static int acx565akm_bl_get_intensity(struct backlight_device *dev) 321 { 322 struct acx565akm_panel *lcd = dev_get_drvdata(&dev->dev); 323 unsigned int intensity; 324 325 mutex_lock(&lcd->mutex); 326 327 if (!backlight_is_blank(dev)) 328 intensity = acx565akm_get_actual_brightness(lcd); 329 else 330 intensity = 0; 331 332 mutex_unlock(&lcd->mutex); 333 334 return intensity; 335 } 336 337 static const struct backlight_ops acx565akm_bl_ops = { 338 .get_brightness = acx565akm_bl_get_intensity, 339 .update_status = acx565akm_bl_update_status, 340 }; 341 342 static int acx565akm_backlight_init(struct acx565akm_panel *lcd) 343 { 344 struct backlight_properties props = { 345 .power = FB_BLANK_UNBLANK, 346 .type = BACKLIGHT_RAW, 347 }; 348 int ret; 349 350 lcd->backlight = backlight_device_register(lcd->name, &lcd->spi->dev, 351 lcd, &acx565akm_bl_ops, 352 &props); 353 if (IS_ERR(lcd->backlight)) { 354 ret = PTR_ERR(lcd->backlight); 355 lcd->backlight = NULL; 356 return ret; 357 } 358 359 if (lcd->has_cabc) { 360 ret = sysfs_create_group(&lcd->backlight->dev.kobj, 361 &acx565akm_cabc_attr_group); 362 if (ret < 0) { 363 dev_err(&lcd->spi->dev, 364 "%s failed to create sysfs files\n", __func__); 365 backlight_device_unregister(lcd->backlight); 366 return ret; 367 } 368 369 lcd->cabc_mode = acx565akm_get_hw_cabc_mode(lcd); 370 } 371 372 lcd->backlight->props.max_brightness = 255; 373 lcd->backlight->props.brightness = acx565akm_get_actual_brightness(lcd); 374 375 acx565akm_bl_update_status_locked(lcd->backlight); 376 377 return 0; 378 } 379 380 static void acx565akm_backlight_cleanup(struct acx565akm_panel *lcd) 381 { 382 if (lcd->has_cabc) 383 sysfs_remove_group(&lcd->backlight->dev.kobj, 384 &acx565akm_cabc_attr_group); 385 386 backlight_device_unregister(lcd->backlight); 387 } 388 389 /* ----------------------------------------------------------------------------- 390 * DRM Bridge Operations 391 */ 392 393 static void acx565akm_set_sleep_mode(struct acx565akm_panel *lcd, int on) 394 { 395 int cmd = on ? MIPI_DCS_ENTER_SLEEP_MODE : MIPI_DCS_EXIT_SLEEP_MODE; 396 unsigned long wait; 397 398 /* 399 * We have to keep 120msec between sleep in/out commands. 400 * (8.2.15, 8.2.16). 401 */ 402 wait = lcd->hw_guard_end - jiffies; 403 if ((long)wait > 0 && wait <= lcd->hw_guard_wait) { 404 set_current_state(TASK_UNINTERRUPTIBLE); 405 schedule_timeout(wait); 406 } 407 408 acx565akm_cmd(lcd, cmd); 409 410 lcd->hw_guard_wait = msecs_to_jiffies(120); 411 lcd->hw_guard_end = jiffies + lcd->hw_guard_wait; 412 } 413 414 static void acx565akm_set_display_state(struct acx565akm_panel *lcd, 415 int enabled) 416 { 417 int cmd = enabled ? MIPI_DCS_SET_DISPLAY_ON : MIPI_DCS_SET_DISPLAY_OFF; 418 419 acx565akm_cmd(lcd, cmd); 420 } 421 422 static int acx565akm_power_on(struct acx565akm_panel *lcd) 423 { 424 /*FIXME tweak me */ 425 msleep(50); 426 427 gpiod_set_value(lcd->reset_gpio, 1); 428 429 if (lcd->enabled) { 430 dev_dbg(&lcd->spi->dev, "panel already enabled\n"); 431 return 0; 432 } 433 434 /* 435 * We have to meet all the following delay requirements: 436 * 1. tRW: reset pulse width 10usec (7.12.1) 437 * 2. tRT: reset cancel time 5msec (7.12.1) 438 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst 439 * case (7.6.2) 440 * 4. 120msec before the sleep out command (7.12.1) 441 */ 442 msleep(120); 443 444 acx565akm_set_sleep_mode(lcd, 0); 445 lcd->enabled = true; 446 447 /* 5msec between sleep out and the next command. (8.2.16) */ 448 usleep_range(5000, 10000); 449 acx565akm_set_display_state(lcd, 1); 450 acx565akm_set_cabc_mode(lcd, lcd->cabc_mode); 451 452 return acx565akm_bl_update_status_locked(lcd->backlight); 453 } 454 455 static void acx565akm_power_off(struct acx565akm_panel *lcd) 456 { 457 if (!lcd->enabled) 458 return; 459 460 acx565akm_set_display_state(lcd, 0); 461 acx565akm_set_sleep_mode(lcd, 1); 462 lcd->enabled = false; 463 /* 464 * We have to provide PCLK,HS,VS signals for 2 frames (worst case 465 * ~50msec) after sending the sleep in command and asserting the 466 * reset signal. We probably could assert the reset w/o the delay 467 * but we still delay to avoid possible artifacts. (7.6.1) 468 */ 469 msleep(50); 470 471 gpiod_set_value(lcd->reset_gpio, 0); 472 473 /* FIXME need to tweak this delay */ 474 msleep(100); 475 } 476 477 static int acx565akm_disable(struct drm_panel *panel) 478 { 479 struct acx565akm_panel *lcd = to_acx565akm_device(panel); 480 481 mutex_lock(&lcd->mutex); 482 acx565akm_power_off(lcd); 483 mutex_unlock(&lcd->mutex); 484 485 return 0; 486 } 487 488 static int acx565akm_enable(struct drm_panel *panel) 489 { 490 struct acx565akm_panel *lcd = to_acx565akm_device(panel); 491 492 mutex_lock(&lcd->mutex); 493 acx565akm_power_on(lcd); 494 mutex_unlock(&lcd->mutex); 495 496 return 0; 497 } 498 499 static const struct drm_display_mode acx565akm_mode = { 500 .clock = 24000, 501 .hdisplay = 800, 502 .hsync_start = 800 + 28, 503 .hsync_end = 800 + 28 + 4, 504 .htotal = 800 + 28 + 4 + 24, 505 .vdisplay = 480, 506 .vsync_start = 480 + 3, 507 .vsync_end = 480 + 3 + 3, 508 .vtotal = 480 + 3 + 3 + 4, 509 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 510 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 511 .width_mm = 77, 512 .height_mm = 46, 513 }; 514 515 static int acx565akm_get_modes(struct drm_panel *panel, 516 struct drm_connector *connector) 517 { 518 struct drm_display_mode *mode; 519 520 mode = drm_mode_duplicate(connector->dev, &acx565akm_mode); 521 if (!mode) 522 return -ENOMEM; 523 524 drm_mode_set_name(mode); 525 drm_mode_probed_add(connector, mode); 526 527 connector->display_info.width_mm = acx565akm_mode.width_mm; 528 connector->display_info.height_mm = acx565akm_mode.height_mm; 529 connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH 530 | DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE 531 | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE; 532 533 return 1; 534 } 535 536 static const struct drm_panel_funcs acx565akm_funcs = { 537 .disable = acx565akm_disable, 538 .enable = acx565akm_enable, 539 .get_modes = acx565akm_get_modes, 540 }; 541 542 /* ----------------------------------------------------------------------------- 543 * Probe, Detect and Remove 544 */ 545 546 static int acx565akm_detect(struct acx565akm_panel *lcd) 547 { 548 __be32 value; 549 u32 status; 550 int ret = 0; 551 552 /* 553 * After being taken out of reset the panel needs 5ms before the first 554 * command can be sent. 555 */ 556 gpiod_set_value(lcd->reset_gpio, 1); 557 usleep_range(5000, 10000); 558 559 acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_STATUS, (u8 *)&value, 4); 560 status = __be32_to_cpu(value); 561 lcd->enabled = (status & (1 << 17)) && (status & (1 << 10)); 562 563 dev_dbg(&lcd->spi->dev, 564 "LCD panel %s by bootloader (status 0x%04x)\n", 565 lcd->enabled ? "enabled" : "disabled ", status); 566 567 acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_ID, lcd->display_id, 3); 568 dev_dbg(&lcd->spi->dev, "MIPI display ID: %02x%02x%02x\n", 569 lcd->display_id[0], lcd->display_id[1], lcd->display_id[2]); 570 571 switch (lcd->display_id[0]) { 572 case 0x10: 573 lcd->model = MIPID_VER_ACX565AKM; 574 lcd->name = "acx565akm"; 575 lcd->has_bc = 1; 576 lcd->has_cabc = 1; 577 break; 578 case 0x29: 579 lcd->model = MIPID_VER_L4F00311; 580 lcd->name = "l4f00311"; 581 break; 582 case 0x45: 583 lcd->model = MIPID_VER_LPH8923; 584 lcd->name = "lph8923"; 585 break; 586 case 0x83: 587 lcd->model = MIPID_VER_LS041Y3; 588 lcd->name = "ls041y3"; 589 break; 590 default: 591 lcd->name = "unknown"; 592 dev_err(&lcd->spi->dev, "unknown display ID\n"); 593 ret = -ENODEV; 594 goto done; 595 } 596 597 lcd->revision = lcd->display_id[1]; 598 599 dev_info(&lcd->spi->dev, "%s rev %02x panel detected\n", 600 lcd->name, lcd->revision); 601 602 done: 603 if (!lcd->enabled) 604 gpiod_set_value(lcd->reset_gpio, 0); 605 606 return ret; 607 } 608 609 static int acx565akm_probe(struct spi_device *spi) 610 { 611 struct acx565akm_panel *lcd; 612 int ret; 613 614 lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL); 615 if (!lcd) 616 return -ENOMEM; 617 618 spi_set_drvdata(spi, lcd); 619 spi->mode = SPI_MODE_3; 620 621 lcd->spi = spi; 622 mutex_init(&lcd->mutex); 623 624 lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH); 625 if (IS_ERR(lcd->reset_gpio)) { 626 dev_err(&spi->dev, "failed to get reset GPIO\n"); 627 return PTR_ERR(lcd->reset_gpio); 628 } 629 630 ret = acx565akm_detect(lcd); 631 if (ret < 0) { 632 dev_err(&spi->dev, "panel detection failed\n"); 633 return ret; 634 } 635 636 if (lcd->has_bc) { 637 ret = acx565akm_backlight_init(lcd); 638 if (ret < 0) 639 return ret; 640 } 641 642 drm_panel_init(&lcd->panel, &lcd->spi->dev, &acx565akm_funcs, 643 DRM_MODE_CONNECTOR_DPI); 644 645 drm_panel_add(&lcd->panel); 646 647 return 0; 648 } 649 650 static void acx565akm_remove(struct spi_device *spi) 651 { 652 struct acx565akm_panel *lcd = spi_get_drvdata(spi); 653 654 drm_panel_remove(&lcd->panel); 655 656 if (lcd->has_bc) 657 acx565akm_backlight_cleanup(lcd); 658 659 drm_panel_disable(&lcd->panel); 660 drm_panel_unprepare(&lcd->panel); 661 } 662 663 static const struct of_device_id acx565akm_of_match[] = { 664 { .compatible = "sony,acx565akm", }, 665 { /* sentinel */ }, 666 }; 667 668 MODULE_DEVICE_TABLE(of, acx565akm_of_match); 669 670 static const struct spi_device_id acx565akm_ids[] = { 671 { "acx565akm", 0 }, 672 { /* sentinel */ } 673 }; 674 675 MODULE_DEVICE_TABLE(spi, acx565akm_ids); 676 677 static struct spi_driver acx565akm_driver = { 678 .probe = acx565akm_probe, 679 .remove = acx565akm_remove, 680 .id_table = acx565akm_ids, 681 .driver = { 682 .name = "panel-sony-acx565akm", 683 .of_match_table = acx565akm_of_match, 684 }, 685 }; 686 687 module_spi_driver(acx565akm_driver); 688 689 MODULE_AUTHOR("Nokia Corporation"); 690 MODULE_DESCRIPTION("Sony ACX565AKM LCD Panel Driver"); 691 MODULE_LICENSE("GPL"); 692