panel-novatek-nt35560.c (13826B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * MIPI-DSI Novatek NT35560-based panel controller. 4 * 5 * Supported panels include: 6 * Sony ACX424AKM - a 480x854 AMOLED DSI panel 7 * Sony ACX424AKP - a 480x864 AMOLED DSI panel 8 * 9 * Copyright (C) Linaro Ltd. 2019-2021 10 * Author: Linus Walleij 11 * Based on code and know-how from Marcus Lorentzon 12 * Copyright (C) ST-Ericsson SA 2010 13 * Based on code and know-how from Johan Olson and Joakim Wesslen 14 * Copyright (C) Sony Ericsson Mobile Communications 2010 15 */ 16#include <linux/backlight.h> 17#include <linux/delay.h> 18#include <linux/gpio/consumer.h> 19#include <linux/module.h> 20#include <linux/of.h> 21#include <linux/of_device.h> 22#include <linux/regulator/consumer.h> 23 24#include <video/mipi_display.h> 25 26#include <drm/drm_mipi_dsi.h> 27#include <drm/drm_modes.h> 28#include <drm/drm_panel.h> 29 30#define NT35560_DCS_READ_ID1 0xDA 31#define NT35560_DCS_READ_ID2 0xDB 32#define NT35560_DCS_READ_ID3 0xDC 33#define NT35560_DCS_SET_MDDI 0xAE 34 35/* 36 * Sony seems to use vendor ID 0x81 37 */ 38#define DISPLAY_SONY_ACX424AKP_ID1 0x8103 39#define DISPLAY_SONY_ACX424AKP_ID2 0x811a 40#define DISPLAY_SONY_ACX424AKP_ID3 0x811b 41/* 42 * The fourth ID looks like a bug, vendor IDs begin at 0x80 43 * and panel 00 ... seems like default values. 44 */ 45#define DISPLAY_SONY_ACX424AKP_ID4 0x8000 46 47struct nt35560_config { 48 const struct drm_display_mode *vid_mode; 49 const struct drm_display_mode *cmd_mode; 50}; 51 52struct nt35560 { 53 const struct nt35560_config *conf; 54 struct drm_panel panel; 55 struct device *dev; 56 struct regulator *supply; 57 struct gpio_desc *reset_gpio; 58 bool video_mode; 59}; 60 61static const struct drm_display_mode sony_acx424akp_vid_mode = { 62 .clock = 27234, 63 .hdisplay = 480, 64 .hsync_start = 480 + 15, 65 .hsync_end = 480 + 15 + 0, 66 .htotal = 480 + 15 + 0 + 15, 67 .vdisplay = 864, 68 .vsync_start = 864 + 14, 69 .vsync_end = 864 + 14 + 1, 70 .vtotal = 864 + 14 + 1 + 11, 71 .width_mm = 48, 72 .height_mm = 84, 73 .flags = DRM_MODE_FLAG_PVSYNC, 74}; 75 76/* 77 * The timings are not very helpful as the display is used in 78 * command mode using the maximum HS frequency. 79 */ 80static const struct drm_display_mode sony_acx424akp_cmd_mode = { 81 .clock = 35478, 82 .hdisplay = 480, 83 .hsync_start = 480 + 154, 84 .hsync_end = 480 + 154 + 16, 85 .htotal = 480 + 154 + 16 + 32, 86 .vdisplay = 864, 87 .vsync_start = 864 + 1, 88 .vsync_end = 864 + 1 + 1, 89 .vtotal = 864 + 1 + 1 + 1, 90 /* 91 * Some desired refresh rate, experiments at the maximum "pixel" 92 * clock speed (HS clock 420 MHz) yields around 117Hz. 93 */ 94 .width_mm = 48, 95 .height_mm = 84, 96}; 97 98static const struct nt35560_config sony_acx424akp_data = { 99 .vid_mode = &sony_acx424akp_vid_mode, 100 .cmd_mode = &sony_acx424akp_cmd_mode, 101}; 102 103static const struct drm_display_mode sony_acx424akm_vid_mode = { 104 .clock = 27234, 105 .hdisplay = 480, 106 .hsync_start = 480 + 15, 107 .hsync_end = 480 + 15 + 0, 108 .htotal = 480 + 15 + 0 + 15, 109 .vdisplay = 854, 110 .vsync_start = 854 + 14, 111 .vsync_end = 854 + 14 + 1, 112 .vtotal = 854 + 14 + 1 + 11, 113 .width_mm = 46, 114 .height_mm = 82, 115 .flags = DRM_MODE_FLAG_PVSYNC, 116}; 117 118/* 119 * The timings are not very helpful as the display is used in 120 * command mode using the maximum HS frequency. 121 */ 122static const struct drm_display_mode sony_acx424akm_cmd_mode = { 123 .clock = 35478, 124 .hdisplay = 480, 125 .hsync_start = 480 + 154, 126 .hsync_end = 480 + 154 + 16, 127 .htotal = 480 + 154 + 16 + 32, 128 .vdisplay = 854, 129 .vsync_start = 854 + 1, 130 .vsync_end = 854 + 1 + 1, 131 .vtotal = 854 + 1 + 1 + 1, 132 .width_mm = 46, 133 .height_mm = 82, 134}; 135 136static const struct nt35560_config sony_acx424akm_data = { 137 .vid_mode = &sony_acx424akm_vid_mode, 138 .cmd_mode = &sony_acx424akm_cmd_mode, 139}; 140 141static inline struct nt35560 *panel_to_nt35560(struct drm_panel *panel) 142{ 143 return container_of(panel, struct nt35560, panel); 144} 145 146#define FOSC 20 /* 20Mhz */ 147#define SCALE_FACTOR_NS_DIV_MHZ 1000 148 149static int nt35560_set_brightness(struct backlight_device *bl) 150{ 151 struct nt35560 *nt = bl_get_data(bl); 152 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev); 153 int period_ns = 1023; 154 int duty_ns = bl->props.brightness; 155 u8 pwm_ratio; 156 u8 pwm_div; 157 u8 par; 158 int ret; 159 160 if (backlight_is_blank(bl)) { 161 /* Disable backlight */ 162 par = 0x00; 163 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 164 &par, 1); 165 if (ret) { 166 dev_err(nt->dev, "failed to disable display backlight (%d)\n", ret); 167 return ret; 168 } 169 return 0; 170 } 171 172 /* Calculate the PWM duty cycle in n/256's */ 173 pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1); 174 pwm_div = max(1, 175 ((FOSC * period_ns) / 256) / 176 SCALE_FACTOR_NS_DIV_MHZ); 177 178 /* Set up PWM dutycycle ONE byte (differs from the standard) */ 179 dev_dbg(nt->dev, "calculated duty cycle %02x\n", pwm_ratio); 180 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 181 &pwm_ratio, 1); 182 if (ret < 0) { 183 dev_err(nt->dev, "failed to set display PWM ratio (%d)\n", ret); 184 return ret; 185 } 186 187 /* 188 * Sequence to write PWMDIV: 189 * address data 190 * 0xF3 0xAA CMD2 Unlock 191 * 0x00 0x01 Enter CMD2 page 0 192 * 0X7D 0x01 No reload MTP of CMD2 P1 193 * 0x22 PWMDIV 194 * 0x7F 0xAA CMD2 page 1 lock 195 */ 196 par = 0xaa; 197 ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1); 198 if (ret < 0) { 199 dev_err(nt->dev, "failed to unlock CMD 2 (%d)\n", ret); 200 return ret; 201 } 202 par = 0x01; 203 ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1); 204 if (ret < 0) { 205 dev_err(nt->dev, "failed to enter page 1 (%d)\n", ret); 206 return ret; 207 } 208 par = 0x01; 209 ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1); 210 if (ret < 0) { 211 dev_err(nt->dev, "failed to disable MTP reload (%d)\n", ret); 212 return ret; 213 } 214 ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1); 215 if (ret < 0) { 216 dev_err(nt->dev, "failed to set PWM divisor (%d)\n", ret); 217 return ret; 218 } 219 par = 0xaa; 220 ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1); 221 if (ret < 0) { 222 dev_err(nt->dev, "failed to lock CMD 2 (%d)\n", ret); 223 return ret; 224 } 225 226 /* Enable backlight */ 227 par = 0x24; 228 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 229 &par, 1); 230 if (ret < 0) { 231 dev_err(nt->dev, "failed to enable display backlight (%d)\n", ret); 232 return ret; 233 } 234 235 return 0; 236} 237 238static const struct backlight_ops nt35560_bl_ops = { 239 .update_status = nt35560_set_brightness, 240}; 241 242static const struct backlight_properties nt35560_bl_props = { 243 .type = BACKLIGHT_RAW, 244 .brightness = 512, 245 .max_brightness = 1023, 246}; 247 248static int nt35560_read_id(struct nt35560 *nt) 249{ 250 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev); 251 u8 vendor, version, panel; 252 u16 val; 253 int ret; 254 255 ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID1, &vendor, 1); 256 if (ret < 0) { 257 dev_err(nt->dev, "could not vendor ID byte\n"); 258 return ret; 259 } 260 ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID2, &version, 1); 261 if (ret < 0) { 262 dev_err(nt->dev, "could not read device version byte\n"); 263 return ret; 264 } 265 ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID3, &panel, 1); 266 if (ret < 0) { 267 dev_err(nt->dev, "could not read panel ID byte\n"); 268 return ret; 269 } 270 271 if (vendor == 0x00) { 272 dev_err(nt->dev, "device vendor ID is zero\n"); 273 return -ENODEV; 274 } 275 276 val = (vendor << 8) | panel; 277 switch (val) { 278 case DISPLAY_SONY_ACX424AKP_ID1: 279 case DISPLAY_SONY_ACX424AKP_ID2: 280 case DISPLAY_SONY_ACX424AKP_ID3: 281 case DISPLAY_SONY_ACX424AKP_ID4: 282 dev_info(nt->dev, "MTP vendor: %02x, version: %02x, panel: %02x\n", 283 vendor, version, panel); 284 break; 285 default: 286 dev_info(nt->dev, "unknown vendor: %02x, version: %02x, panel: %02x\n", 287 vendor, version, panel); 288 break; 289 } 290 291 return 0; 292} 293 294static int nt35560_power_on(struct nt35560 *nt) 295{ 296 int ret; 297 298 ret = regulator_enable(nt->supply); 299 if (ret) { 300 dev_err(nt->dev, "failed to enable supply (%d)\n", ret); 301 return ret; 302 } 303 304 /* Assert RESET */ 305 gpiod_set_value_cansleep(nt->reset_gpio, 1); 306 udelay(20); 307 /* De-assert RESET */ 308 gpiod_set_value_cansleep(nt->reset_gpio, 0); 309 usleep_range(11000, 20000); 310 311 return 0; 312} 313 314static void nt35560_power_off(struct nt35560 *nt) 315{ 316 /* Assert RESET */ 317 gpiod_set_value_cansleep(nt->reset_gpio, 1); 318 usleep_range(11000, 20000); 319 320 regulator_disable(nt->supply); 321} 322 323static int nt35560_prepare(struct drm_panel *panel) 324{ 325 struct nt35560 *nt = panel_to_nt35560(panel); 326 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev); 327 const u8 mddi = 3; 328 int ret; 329 330 ret = nt35560_power_on(nt); 331 if (ret) 332 return ret; 333 334 ret = nt35560_read_id(nt); 335 if (ret) { 336 dev_err(nt->dev, "failed to read panel ID (%d)\n", ret); 337 goto err_power_off; 338 } 339 340 /* Enabe tearing mode: send TE (tearing effect) at VBLANK */ 341 ret = mipi_dsi_dcs_set_tear_on(dsi, 342 MIPI_DSI_DCS_TEAR_MODE_VBLANK); 343 if (ret) { 344 dev_err(nt->dev, "failed to enable vblank TE (%d)\n", ret); 345 goto err_power_off; 346 } 347 348 /* 349 * Set MDDI 350 * 351 * This presumably deactivates the Qualcomm MDDI interface and 352 * selects DSI, similar code is found in other drivers such as the 353 * Sharp LS043T1LE01 which makes us suspect that this panel may be 354 * using a Novatek NT35565 or similar display driver chip that shares 355 * this command. Due to the lack of documentation we cannot know for 356 * sure. 357 */ 358 ret = mipi_dsi_dcs_write(dsi, NT35560_DCS_SET_MDDI, 359 &mddi, sizeof(mddi)); 360 if (ret < 0) { 361 dev_err(nt->dev, "failed to set MDDI (%d)\n", ret); 362 goto err_power_off; 363 } 364 365 /* Exit sleep mode */ 366 ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 367 if (ret) { 368 dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret); 369 goto err_power_off; 370 } 371 msleep(140); 372 373 ret = mipi_dsi_dcs_set_display_on(dsi); 374 if (ret) { 375 dev_err(nt->dev, "failed to turn display on (%d)\n", ret); 376 goto err_power_off; 377 } 378 if (nt->video_mode) { 379 /* In video mode turn peripheral on */ 380 ret = mipi_dsi_turn_on_peripheral(dsi); 381 if (ret) { 382 dev_err(nt->dev, "failed to turn on peripheral\n"); 383 goto err_power_off; 384 } 385 } 386 387 return 0; 388 389err_power_off: 390 nt35560_power_off(nt); 391 return ret; 392} 393 394static int nt35560_unprepare(struct drm_panel *panel) 395{ 396 struct nt35560 *nt = panel_to_nt35560(panel); 397 struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev); 398 int ret; 399 400 ret = mipi_dsi_dcs_set_display_off(dsi); 401 if (ret) { 402 dev_err(nt->dev, "failed to turn display off (%d)\n", ret); 403 return ret; 404 } 405 406 /* Enter sleep mode */ 407 ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 408 if (ret) { 409 dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret); 410 return ret; 411 } 412 msleep(85); 413 414 nt35560_power_off(nt); 415 416 return 0; 417} 418 419 420static int nt35560_get_modes(struct drm_panel *panel, 421 struct drm_connector *connector) 422{ 423 struct nt35560 *nt = panel_to_nt35560(panel); 424 const struct nt35560_config *conf = nt->conf; 425 struct drm_display_mode *mode; 426 427 if (nt->video_mode) 428 mode = drm_mode_duplicate(connector->dev, 429 conf->vid_mode); 430 else 431 mode = drm_mode_duplicate(connector->dev, 432 conf->cmd_mode); 433 if (!mode) { 434 dev_err(panel->dev, "bad mode or failed to add mode\n"); 435 return -EINVAL; 436 } 437 drm_mode_set_name(mode); 438 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 439 440 connector->display_info.width_mm = mode->width_mm; 441 connector->display_info.height_mm = mode->height_mm; 442 443 drm_mode_probed_add(connector, mode); 444 445 return 1; /* Number of modes */ 446} 447 448static const struct drm_panel_funcs nt35560_drm_funcs = { 449 .unprepare = nt35560_unprepare, 450 .prepare = nt35560_prepare, 451 .get_modes = nt35560_get_modes, 452}; 453 454static int nt35560_probe(struct mipi_dsi_device *dsi) 455{ 456 struct device *dev = &dsi->dev; 457 struct nt35560 *nt; 458 int ret; 459 460 nt = devm_kzalloc(dev, sizeof(struct nt35560), GFP_KERNEL); 461 if (!nt) 462 return -ENOMEM; 463 nt->video_mode = of_property_read_bool(dev->of_node, 464 "enforce-video-mode"); 465 466 mipi_dsi_set_drvdata(dsi, nt); 467 nt->dev = dev; 468 469 nt->conf = of_device_get_match_data(dev); 470 if (!nt->conf) { 471 dev_err(dev, "missing device configuration\n"); 472 return -ENODEV; 473 } 474 475 dsi->lanes = 2; 476 dsi->format = MIPI_DSI_FMT_RGB888; 477 /* 478 * FIXME: these come from the ST-Ericsson vendor driver for the 479 * HREF520 and seems to reflect limitations in the PLLs on that 480 * platform, if you have the datasheet, please cross-check the 481 * actual max rates. 482 */ 483 dsi->lp_rate = 19200000; 484 dsi->hs_rate = 420160000; 485 486 if (nt->video_mode) 487 /* Burst mode using event for sync */ 488 dsi->mode_flags = 489 MIPI_DSI_MODE_VIDEO | 490 MIPI_DSI_MODE_VIDEO_BURST; 491 else 492 dsi->mode_flags = 493 MIPI_DSI_CLOCK_NON_CONTINUOUS; 494 495 nt->supply = devm_regulator_get(dev, "vddi"); 496 if (IS_ERR(nt->supply)) 497 return PTR_ERR(nt->supply); 498 499 /* This asserts RESET by default */ 500 nt->reset_gpio = devm_gpiod_get_optional(dev, "reset", 501 GPIOD_OUT_HIGH); 502 if (IS_ERR(nt->reset_gpio)) 503 return dev_err_probe(dev, PTR_ERR(nt->reset_gpio), 504 "failed to request GPIO\n"); 505 506 drm_panel_init(&nt->panel, dev, &nt35560_drm_funcs, 507 DRM_MODE_CONNECTOR_DSI); 508 509 nt->panel.backlight = devm_backlight_device_register(dev, "nt35560", dev, nt, 510 &nt35560_bl_ops, &nt35560_bl_props); 511 if (IS_ERR(nt->panel.backlight)) 512 return dev_err_probe(dev, PTR_ERR(nt->panel.backlight), 513 "failed to register backlight device\n"); 514 515 drm_panel_add(&nt->panel); 516 517 ret = mipi_dsi_attach(dsi); 518 if (ret < 0) { 519 drm_panel_remove(&nt->panel); 520 return ret; 521 } 522 523 return 0; 524} 525 526static int nt35560_remove(struct mipi_dsi_device *dsi) 527{ 528 struct nt35560 *nt = mipi_dsi_get_drvdata(dsi); 529 530 mipi_dsi_detach(dsi); 531 drm_panel_remove(&nt->panel); 532 533 return 0; 534} 535 536static const struct of_device_id nt35560_of_match[] = { 537 { 538 .compatible = "sony,acx424akp", 539 .data = &sony_acx424akp_data, 540 }, 541 { 542 .compatible = "sony,acx424akm", 543 .data = &sony_acx424akm_data, 544 }, 545 { /* sentinel */ } 546}; 547MODULE_DEVICE_TABLE(of, nt35560_of_match); 548 549static struct mipi_dsi_driver nt35560_driver = { 550 .probe = nt35560_probe, 551 .remove = nt35560_remove, 552 .driver = { 553 .name = "panel-novatek-nt35560", 554 .of_match_table = nt35560_of_match, 555 }, 556}; 557module_mipi_dsi_driver(nt35560_driver); 558 559MODULE_AUTHOR("Linus Wallei <linus.walleij@linaro.org>"); 560MODULE_DESCRIPTION("MIPI-DSI Novatek NT35560 Panel Driver"); 561MODULE_LICENSE("GPL v2");