1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2019 Theobroma Systems Design und Consulting GmbH 4 * 5 * base on panel-kingdisplay-kd097d04.c 6 * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd 7 */ 8 9 #include <linux/backlight.h> 10 #include <linux/delay.h> 11 #include <linux/gpio/consumer.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/regulator/consumer.h> 15 16 #include <video/mipi_display.h> 17 18 #include <drm/drm_crtc.h> 19 #include <drm/drm_device.h> 20 #include <drm/drm_mipi_dsi.h> 21 #include <drm/drm_modes.h> 22 #include <drm/drm_panel.h> 23 #include <drm/drm_print.h> 24 25 struct ltk500hd1829 { 26 struct device *dev; 27 struct drm_panel panel; 28 struct gpio_desc *reset_gpio; 29 struct regulator *vcc; 30 struct regulator *iovcc; 31 bool prepared; 32 }; 33 34 struct ltk500hd1829_cmd { 35 char cmd; 36 char data; 37 }; 38 39 /* 40 * There is no description in the Reference Manual about these commands. 41 * We received them from the vendor, so just use them as is. 42 */ 43 static const struct ltk500hd1829_cmd init_code[] = { 44 { 0xE0, 0x00 }, 45 { 0xE1, 0x93 }, 46 { 0xE2, 0x65 }, 47 { 0xE3, 0xF8 }, 48 { 0x80, 0x03 }, 49 { 0xE0, 0x04 }, 50 { 0x2D, 0x03 }, 51 { 0xE0, 0x01 }, 52 { 0x00, 0x00 }, 53 { 0x01, 0xB6 }, 54 { 0x03, 0x00 }, 55 { 0x04, 0xC5 }, 56 { 0x17, 0x00 }, 57 { 0x18, 0xBF }, 58 { 0x19, 0x01 }, 59 { 0x1A, 0x00 }, 60 { 0x1B, 0xBF }, 61 { 0x1C, 0x01 }, 62 { 0x1F, 0x7C }, 63 { 0x20, 0x26 }, 64 { 0x21, 0x26 }, 65 { 0x22, 0x4E }, 66 { 0x37, 0x09 }, 67 { 0x38, 0x04 }, 68 { 0x39, 0x08 }, 69 { 0x3A, 0x1F }, 70 { 0x3B, 0x1F }, 71 { 0x3C, 0x78 }, 72 { 0x3D, 0xFF }, 73 { 0x3E, 0xFF }, 74 { 0x3F, 0x00 }, 75 { 0x40, 0x04 }, 76 { 0x41, 0xA0 }, 77 { 0x43, 0x0F }, 78 { 0x44, 0x0A }, 79 { 0x45, 0x24 }, 80 { 0x55, 0x01 }, 81 { 0x56, 0x01 }, 82 { 0x57, 0xA5 }, 83 { 0x58, 0x0A }, 84 { 0x59, 0x4A }, 85 { 0x5A, 0x38 }, 86 { 0x5B, 0x10 }, 87 { 0x5C, 0x19 }, 88 { 0x5D, 0x7C }, 89 { 0x5E, 0x64 }, 90 { 0x5F, 0x54 }, 91 { 0x60, 0x48 }, 92 { 0x61, 0x44 }, 93 { 0x62, 0x35 }, 94 { 0x63, 0x3A }, 95 { 0x64, 0x24 }, 96 { 0x65, 0x3B }, 97 { 0x66, 0x39 }, 98 { 0x67, 0x37 }, 99 { 0x68, 0x56 }, 100 { 0x69, 0x41 }, 101 { 0x6A, 0x47 }, 102 { 0x6B, 0x2F }, 103 { 0x6C, 0x23 }, 104 { 0x6D, 0x13 }, 105 { 0x6E, 0x02 }, 106 { 0x6F, 0x08 }, 107 { 0x70, 0x7C }, 108 { 0x71, 0x64 }, 109 { 0x72, 0x54 }, 110 { 0x73, 0x48 }, 111 { 0x74, 0x44 }, 112 { 0x75, 0x35 }, 113 { 0x76, 0x3A }, 114 { 0x77, 0x22 }, 115 { 0x78, 0x3B }, 116 { 0x79, 0x39 }, 117 { 0x7A, 0x38 }, 118 { 0x7B, 0x52 }, 119 { 0x7C, 0x41 }, 120 { 0x7D, 0x47 }, 121 { 0x7E, 0x2F }, 122 { 0x7F, 0x23 }, 123 { 0x80, 0x13 }, 124 { 0x81, 0x02 }, 125 { 0x82, 0x08 }, 126 { 0xE0, 0x02 }, 127 { 0x00, 0x57 }, 128 { 0x01, 0x77 }, 129 { 0x02, 0x44 }, 130 { 0x03, 0x46 }, 131 { 0x04, 0x48 }, 132 { 0x05, 0x4A }, 133 { 0x06, 0x4C }, 134 { 0x07, 0x4E }, 135 { 0x08, 0x50 }, 136 { 0x09, 0x55 }, 137 { 0x0A, 0x52 }, 138 { 0x0B, 0x55 }, 139 { 0x0C, 0x55 }, 140 { 0x0D, 0x55 }, 141 { 0x0E, 0x55 }, 142 { 0x0F, 0x55 }, 143 { 0x10, 0x55 }, 144 { 0x11, 0x55 }, 145 { 0x12, 0x55 }, 146 { 0x13, 0x40 }, 147 { 0x14, 0x55 }, 148 { 0x15, 0x55 }, 149 { 0x16, 0x57 }, 150 { 0x17, 0x77 }, 151 { 0x18, 0x45 }, 152 { 0x19, 0x47 }, 153 { 0x1A, 0x49 }, 154 { 0x1B, 0x4B }, 155 { 0x1C, 0x4D }, 156 { 0x1D, 0x4F }, 157 { 0x1E, 0x51 }, 158 { 0x1F, 0x55 }, 159 { 0x20, 0x53 }, 160 { 0x21, 0x55 }, 161 { 0x22, 0x55 }, 162 { 0x23, 0x55 }, 163 { 0x24, 0x55 }, 164 { 0x25, 0x55 }, 165 { 0x26, 0x55 }, 166 { 0x27, 0x55 }, 167 { 0x28, 0x55 }, 168 { 0x29, 0x41 }, 169 { 0x2A, 0x55 }, 170 { 0x2B, 0x55 }, 171 { 0x2C, 0x57 }, 172 { 0x2D, 0x77 }, 173 { 0x2E, 0x4F }, 174 { 0x2F, 0x4D }, 175 { 0x30, 0x4B }, 176 { 0x31, 0x49 }, 177 { 0x32, 0x47 }, 178 { 0x33, 0x45 }, 179 { 0x34, 0x41 }, 180 { 0x35, 0x55 }, 181 { 0x36, 0x53 }, 182 { 0x37, 0x55 }, 183 { 0x38, 0x55 }, 184 { 0x39, 0x55 }, 185 { 0x3A, 0x55 }, 186 { 0x3B, 0x55 }, 187 { 0x3C, 0x55 }, 188 { 0x3D, 0x55 }, 189 { 0x3E, 0x55 }, 190 { 0x3F, 0x51 }, 191 { 0x40, 0x55 }, 192 { 0x41, 0x55 }, 193 { 0x42, 0x57 }, 194 { 0x43, 0x77 }, 195 { 0x44, 0x4E }, 196 { 0x45, 0x4C }, 197 { 0x46, 0x4A }, 198 { 0x47, 0x48 }, 199 { 0x48, 0x46 }, 200 { 0x49, 0x44 }, 201 { 0x4A, 0x40 }, 202 { 0x4B, 0x55 }, 203 { 0x4C, 0x52 }, 204 { 0x4D, 0x55 }, 205 { 0x4E, 0x55 }, 206 { 0x4F, 0x55 }, 207 { 0x50, 0x55 }, 208 { 0x51, 0x55 }, 209 { 0x52, 0x55 }, 210 { 0x53, 0x55 }, 211 { 0x54, 0x55 }, 212 { 0x55, 0x50 }, 213 { 0x56, 0x55 }, 214 { 0x57, 0x55 }, 215 { 0x58, 0x40 }, 216 { 0x59, 0x00 }, 217 { 0x5A, 0x00 }, 218 { 0x5B, 0x10 }, 219 { 0x5C, 0x09 }, 220 { 0x5D, 0x30 }, 221 { 0x5E, 0x01 }, 222 { 0x5F, 0x02 }, 223 { 0x60, 0x30 }, 224 { 0x61, 0x03 }, 225 { 0x62, 0x04 }, 226 { 0x63, 0x06 }, 227 { 0x64, 0x6A }, 228 { 0x65, 0x75 }, 229 { 0x66, 0x0F }, 230 { 0x67, 0xB3 }, 231 { 0x68, 0x0B }, 232 { 0x69, 0x06 }, 233 { 0x6A, 0x6A }, 234 { 0x6B, 0x10 }, 235 { 0x6C, 0x00 }, 236 { 0x6D, 0x04 }, 237 { 0x6E, 0x04 }, 238 { 0x6F, 0x88 }, 239 { 0x70, 0x00 }, 240 { 0x71, 0x00 }, 241 { 0x72, 0x06 }, 242 { 0x73, 0x7B }, 243 { 0x74, 0x00 }, 244 { 0x75, 0xBC }, 245 { 0x76, 0x00 }, 246 { 0x77, 0x05 }, 247 { 0x78, 0x2E }, 248 { 0x79, 0x00 }, 249 { 0x7A, 0x00 }, 250 { 0x7B, 0x00 }, 251 { 0x7C, 0x00 }, 252 { 0x7D, 0x03 }, 253 { 0x7E, 0x7B }, 254 { 0xE0, 0x04 }, 255 { 0x09, 0x10 }, 256 { 0x2B, 0x2B }, 257 { 0x2E, 0x44 }, 258 { 0xE0, 0x00 }, 259 { 0xE6, 0x02 }, 260 { 0xE7, 0x02 }, 261 { 0x35, 0x00 }, 262 }; 263 264 static inline 265 struct ltk500hd1829 *panel_to_ltk500hd1829(struct drm_panel *panel) 266 { 267 return container_of(panel, struct ltk500hd1829, panel); 268 } 269 270 static int ltk500hd1829_unprepare(struct drm_panel *panel) 271 { 272 struct ltk500hd1829 *ctx = panel_to_ltk500hd1829(panel); 273 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 274 int ret; 275 276 if (!ctx->prepared) 277 return 0; 278 279 ret = mipi_dsi_dcs_set_display_off(dsi); 280 if (ret < 0) 281 DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", 282 ret); 283 284 ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 285 if (ret < 0) { 286 DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", 287 ret); 288 } 289 290 /* 120ms to enter sleep mode */ 291 msleep(120); 292 293 regulator_disable(ctx->iovcc); 294 regulator_disable(ctx->vcc); 295 296 ctx->prepared = false; 297 298 return 0; 299 } 300 301 static int ltk500hd1829_prepare(struct drm_panel *panel) 302 { 303 struct ltk500hd1829 *ctx = panel_to_ltk500hd1829(panel); 304 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 305 unsigned int i; 306 int ret; 307 308 if (ctx->prepared) 309 return 0; 310 311 ret = regulator_enable(ctx->vcc); 312 if (ret < 0) { 313 DRM_DEV_ERROR(ctx->dev, 314 "Failed to enable vci supply: %d\n", ret); 315 return ret; 316 } 317 ret = regulator_enable(ctx->iovcc); 318 if (ret < 0) { 319 DRM_DEV_ERROR(ctx->dev, 320 "Failed to enable iovcc supply: %d\n", ret); 321 goto disable_vcc; 322 } 323 324 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 325 /* tRW: 10us */ 326 usleep_range(10, 20); 327 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 328 329 /* tRT: >= 5ms */ 330 usleep_range(5000, 6000); 331 332 for (i = 0; i < ARRAY_SIZE(init_code); i++) { 333 ret = mipi_dsi_generic_write(dsi, &init_code[i], 334 sizeof(struct ltk500hd1829_cmd)); 335 if (ret < 0) { 336 DRM_DEV_ERROR(panel->dev, 337 "failed to write init cmds: %d\n", ret); 338 goto disable_iovcc; 339 } 340 } 341 342 ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 343 if (ret < 0) { 344 DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n", 345 ret); 346 goto disable_iovcc; 347 } 348 349 /* 120ms to exit sleep mode */ 350 msleep(120); 351 352 ret = mipi_dsi_dcs_set_display_on(dsi); 353 if (ret < 0) { 354 DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", 355 ret); 356 goto disable_iovcc; 357 } 358 359 ctx->prepared = true; 360 361 return 0; 362 363 disable_iovcc: 364 regulator_disable(ctx->iovcc); 365 disable_vcc: 366 regulator_disable(ctx->vcc); 367 return ret; 368 } 369 370 static const struct drm_display_mode default_mode = { 371 .hdisplay = 720, 372 .hsync_start = 720 + 50, 373 .hsync_end = 720 + 50 + 50, 374 .htotal = 720 + 50 + 50 + 50, 375 .vdisplay = 1280, 376 .vsync_start = 1280 + 30, 377 .vsync_end = 1280 + 30 + 4, 378 .vtotal = 1280 + 30 + 4 + 12, 379 .vrefresh = 60, 380 .clock = 69217, 381 .width_mm = 62, 382 .height_mm = 110, 383 }; 384 385 static int ltk500hd1829_get_modes(struct drm_panel *panel, 386 struct drm_connector *connector) 387 { 388 struct ltk500hd1829 *ctx = panel_to_ltk500hd1829(panel); 389 struct drm_display_mode *mode; 390 391 mode = drm_mode_duplicate(connector->dev, &default_mode); 392 if (!mode) { 393 DRM_DEV_ERROR(ctx->dev, "failed to add mode %ux%ux@%u\n", 394 default_mode.hdisplay, default_mode.vdisplay, 395 default_mode.vrefresh); 396 return -ENOMEM; 397 } 398 399 drm_mode_set_name(mode); 400 401 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 402 connector->display_info.width_mm = mode->width_mm; 403 connector->display_info.height_mm = mode->height_mm; 404 drm_mode_probed_add(connector, mode); 405 406 return 1; 407 } 408 409 static const struct drm_panel_funcs ltk500hd1829_funcs = { 410 .unprepare = ltk500hd1829_unprepare, 411 .prepare = ltk500hd1829_prepare, 412 .get_modes = ltk500hd1829_get_modes, 413 }; 414 415 static int ltk500hd1829_probe(struct mipi_dsi_device *dsi) 416 { 417 struct ltk500hd1829 *ctx; 418 struct device *dev = &dsi->dev; 419 int ret; 420 421 ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); 422 if (!ctx) 423 return -ENOMEM; 424 425 ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 426 if (IS_ERR(ctx->reset_gpio)) { 427 DRM_DEV_ERROR(dev, "cannot get reset gpio\n"); 428 return PTR_ERR(ctx->reset_gpio); 429 } 430 431 ctx->vcc = devm_regulator_get(dev, "vcc"); 432 if (IS_ERR(ctx->vcc)) { 433 ret = PTR_ERR(ctx->vcc); 434 if (ret != -EPROBE_DEFER) 435 DRM_DEV_ERROR(dev, 436 "Failed to request vcc regulator: %d\n", 437 ret); 438 return ret; 439 } 440 441 ctx->iovcc = devm_regulator_get(dev, "iovcc"); 442 if (IS_ERR(ctx->iovcc)) { 443 ret = PTR_ERR(ctx->iovcc); 444 if (ret != -EPROBE_DEFER) 445 DRM_DEV_ERROR(dev, 446 "Failed to request iovcc regulator: %d\n", 447 ret); 448 return ret; 449 } 450 451 mipi_dsi_set_drvdata(dsi, ctx); 452 453 ctx->dev = dev; 454 455 dsi->lanes = 4; 456 dsi->format = MIPI_DSI_FMT_RGB888; 457 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 458 MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET; 459 460 drm_panel_init(&ctx->panel, &dsi->dev, <k500hd1829_funcs, 461 DRM_MODE_CONNECTOR_DSI); 462 463 ret = drm_panel_of_backlight(&ctx->panel); 464 if (ret) 465 return ret; 466 467 drm_panel_add(&ctx->panel); 468 469 ret = mipi_dsi_attach(dsi); 470 if (ret < 0) { 471 DRM_DEV_ERROR(dev, "mipi_dsi_attach failed: %d\n", ret); 472 drm_panel_remove(&ctx->panel); 473 return ret; 474 } 475 476 return 0; 477 } 478 479 static void ltk500hd1829_shutdown(struct mipi_dsi_device *dsi) 480 { 481 struct ltk500hd1829 *ctx = mipi_dsi_get_drvdata(dsi); 482 int ret; 483 484 ret = drm_panel_unprepare(&ctx->panel); 485 if (ret < 0) 486 DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", 487 ret); 488 489 ret = drm_panel_disable(&ctx->panel); 490 if (ret < 0) 491 DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", 492 ret); 493 } 494 495 static int ltk500hd1829_remove(struct mipi_dsi_device *dsi) 496 { 497 struct ltk500hd1829 *ctx = mipi_dsi_get_drvdata(dsi); 498 int ret; 499 500 ltk500hd1829_shutdown(dsi); 501 502 ret = mipi_dsi_detach(dsi); 503 if (ret < 0) 504 DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n", 505 ret); 506 507 drm_panel_remove(&ctx->panel); 508 509 return 0; 510 } 511 512 static const struct of_device_id ltk500hd1829_of_match[] = { 513 { .compatible = "leadtek,ltk500hd1829", }, 514 { /* sentinel */ } 515 }; 516 MODULE_DEVICE_TABLE(of, ltk500hd1829_of_match); 517 518 static struct mipi_dsi_driver ltk500hd1829_driver = { 519 .driver = { 520 .name = "panel-leadtek-ltk500hd1829", 521 .of_match_table = ltk500hd1829_of_match, 522 }, 523 .probe = ltk500hd1829_probe, 524 .remove = ltk500hd1829_remove, 525 .shutdown = ltk500hd1829_shutdown, 526 }; 527 module_mipi_dsi_driver(ltk500hd1829_driver); 528 529 MODULE_AUTHOR("Heiko Stuebner <heiko.stuebner@theobroma-systems.com>"); 530 MODULE_DESCRIPTION("Leadtek LTK500HD1829 panel driver"); 531 MODULE_LICENSE("GPL v2"); 532