1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/backlight.h> 7 #include <linux/delay.h> 8 #include <linux/gpio/consumer.h> 9 #include <linux/module.h> 10 #include <linux/of_device.h> 11 #include <linux/of_graph.h> 12 #include <linux/pinctrl/consumer.h> 13 #include <linux/regulator/consumer.h> 14 15 #include <video/mipi_display.h> 16 17 #include <drm/drm_mipi_dsi.h> 18 #include <drm/drm_modes.h> 19 #include <drm/drm_panel.h> 20 #include <drm/drm_print.h> 21 22 static const char * const regulator_names[] = { 23 "vdda", 24 "vdispp", 25 "vdispn", 26 }; 27 28 static unsigned long const regulator_enable_loads[] = { 29 62000, 30 100000, 31 100000, 32 }; 33 34 static unsigned long const regulator_disable_loads[] = { 35 80, 36 100, 37 100, 38 }; 39 40 struct cmd_set { 41 u8 commands[4]; 42 u8 size; 43 }; 44 45 struct nt35597_config { 46 u32 width_mm; 47 u32 height_mm; 48 const char *panel_name; 49 const struct cmd_set *panel_on_cmds; 50 u32 num_on_cmds; 51 const struct drm_display_mode *dm; 52 }; 53 54 struct truly_nt35597 { 55 struct device *dev; 56 struct drm_panel panel; 57 58 struct regulator_bulk_data supplies[ARRAY_SIZE(regulator_names)]; 59 60 struct gpio_desc *reset_gpio; 61 struct gpio_desc *mode_gpio; 62 63 struct backlight_device *backlight; 64 65 struct mipi_dsi_device *dsi[2]; 66 67 const struct nt35597_config *config; 68 bool prepared; 69 bool enabled; 70 }; 71 72 static inline struct truly_nt35597 *panel_to_ctx(struct drm_panel *panel) 73 { 74 return container_of(panel, struct truly_nt35597, panel); 75 } 76 77 static const struct cmd_set qcom_2k_panel_magic_cmds[] = { 78 /* CMD2_P0 */ 79 { { 0xff, 0x20 }, 2 }, 80 { { 0xfb, 0x01 }, 2 }, 81 { { 0x00, 0x01 }, 2 }, 82 { { 0x01, 0x55 }, 2 }, 83 { { 0x02, 0x45 }, 2 }, 84 { { 0x05, 0x40 }, 2 }, 85 { { 0x06, 0x19 }, 2 }, 86 { { 0x07, 0x1e }, 2 }, 87 { { 0x0b, 0x73 }, 2 }, 88 { { 0x0c, 0x73 }, 2 }, 89 { { 0x0e, 0xb0 }, 2 }, 90 { { 0x0f, 0xae }, 2 }, 91 { { 0x11, 0xb8 }, 2 }, 92 { { 0x13, 0x00 }, 2 }, 93 { { 0x58, 0x80 }, 2 }, 94 { { 0x59, 0x01 }, 2 }, 95 { { 0x5a, 0x00 }, 2 }, 96 { { 0x5b, 0x01 }, 2 }, 97 { { 0x5c, 0x80 }, 2 }, 98 { { 0x5d, 0x81 }, 2 }, 99 { { 0x5e, 0x00 }, 2 }, 100 { { 0x5f, 0x01 }, 2 }, 101 { { 0x72, 0x11 }, 2 }, 102 { { 0x68, 0x03 }, 2 }, 103 /* CMD2_P4 */ 104 { { 0xFF, 0x24 }, 2 }, 105 { { 0xFB, 0x01 }, 2 }, 106 { { 0x00, 0x1C }, 2 }, 107 { { 0x01, 0x0B }, 2 }, 108 { { 0x02, 0x0C }, 2 }, 109 { { 0x03, 0x01 }, 2 }, 110 { { 0x04, 0x0F }, 2 }, 111 { { 0x05, 0x10 }, 2 }, 112 { { 0x06, 0x10 }, 2 }, 113 { { 0x07, 0x10 }, 2 }, 114 { { 0x08, 0x89 }, 2 }, 115 { { 0x09, 0x8A }, 2 }, 116 { { 0x0A, 0x13 }, 2 }, 117 { { 0x0B, 0x13 }, 2 }, 118 { { 0x0C, 0x15 }, 2 }, 119 { { 0x0D, 0x15 }, 2 }, 120 { { 0x0E, 0x17 }, 2 }, 121 { { 0x0F, 0x17 }, 2 }, 122 { { 0x10, 0x1C }, 2 }, 123 { { 0x11, 0x0B }, 2 }, 124 { { 0x12, 0x0C }, 2 }, 125 { { 0x13, 0x01 }, 2 }, 126 { { 0x14, 0x0F }, 2 }, 127 { { 0x15, 0x10 }, 2 }, 128 { { 0x16, 0x10 }, 2 }, 129 { { 0x17, 0x10 }, 2 }, 130 { { 0x18, 0x89 }, 2 }, 131 { { 0x19, 0x8A }, 2 }, 132 { { 0x1A, 0x13 }, 2 }, 133 { { 0x1B, 0x13 }, 2 }, 134 { { 0x1C, 0x15 }, 2 }, 135 { { 0x1D, 0x15 }, 2 }, 136 { { 0x1E, 0x17 }, 2 }, 137 { { 0x1F, 0x17 }, 2 }, 138 /* STV */ 139 { { 0x20, 0x40 }, 2 }, 140 { { 0x21, 0x01 }, 2 }, 141 { { 0x22, 0x00 }, 2 }, 142 { { 0x23, 0x40 }, 2 }, 143 { { 0x24, 0x40 }, 2 }, 144 { { 0x25, 0x6D }, 2 }, 145 { { 0x26, 0x40 }, 2 }, 146 { { 0x27, 0x40 }, 2 }, 147 /* Vend */ 148 { { 0xE0, 0x00 }, 2 }, 149 { { 0xDC, 0x21 }, 2 }, 150 { { 0xDD, 0x22 }, 2 }, 151 { { 0xDE, 0x07 }, 2 }, 152 { { 0xDF, 0x07 }, 2 }, 153 { { 0xE3, 0x6D }, 2 }, 154 { { 0xE1, 0x07 }, 2 }, 155 { { 0xE2, 0x07 }, 2 }, 156 /* UD */ 157 { { 0x29, 0xD8 }, 2 }, 158 { { 0x2A, 0x2A }, 2 }, 159 /* CLK */ 160 { { 0x4B, 0x03 }, 2 }, 161 { { 0x4C, 0x11 }, 2 }, 162 { { 0x4D, 0x10 }, 2 }, 163 { { 0x4E, 0x01 }, 2 }, 164 { { 0x4F, 0x01 }, 2 }, 165 { { 0x50, 0x10 }, 2 }, 166 { { 0x51, 0x00 }, 2 }, 167 { { 0x52, 0x80 }, 2 }, 168 { { 0x53, 0x00 }, 2 }, 169 { { 0x56, 0x00 }, 2 }, 170 { { 0x54, 0x07 }, 2 }, 171 { { 0x58, 0x07 }, 2 }, 172 { { 0x55, 0x25 }, 2 }, 173 /* Reset XDONB */ 174 { { 0x5B, 0x43 }, 2 }, 175 { { 0x5C, 0x00 }, 2 }, 176 { { 0x5F, 0x73 }, 2 }, 177 { { 0x60, 0x73 }, 2 }, 178 { { 0x63, 0x22 }, 2 }, 179 { { 0x64, 0x00 }, 2 }, 180 { { 0x67, 0x08 }, 2 }, 181 { { 0x68, 0x04 }, 2 }, 182 /* Resolution:1440x2560 */ 183 { { 0x72, 0x02 }, 2 }, 184 /* mux */ 185 { { 0x7A, 0x80 }, 2 }, 186 { { 0x7B, 0x91 }, 2 }, 187 { { 0x7C, 0xD8 }, 2 }, 188 { { 0x7D, 0x60 }, 2 }, 189 { { 0x7F, 0x15 }, 2 }, 190 { { 0x75, 0x15 }, 2 }, 191 /* ABOFF */ 192 { { 0xB3, 0xC0 }, 2 }, 193 { { 0xB4, 0x00 }, 2 }, 194 { { 0xB5, 0x00 }, 2 }, 195 /* Source EQ */ 196 { { 0x78, 0x00 }, 2 }, 197 { { 0x79, 0x00 }, 2 }, 198 { { 0x80, 0x00 }, 2 }, 199 { { 0x83, 0x00 }, 2 }, 200 /* FP BP */ 201 { { 0x93, 0x0A }, 2 }, 202 { { 0x94, 0x0A }, 2 }, 203 /* Inversion Type */ 204 { { 0x8A, 0x00 }, 2 }, 205 { { 0x9B, 0xFF }, 2 }, 206 /* IMGSWAP =1 @PortSwap=1 */ 207 { { 0x9D, 0xB0 }, 2 }, 208 { { 0x9F, 0x63 }, 2 }, 209 { { 0x98, 0x10 }, 2 }, 210 /* FRM */ 211 { { 0xEC, 0x00 }, 2 }, 212 /* CMD1 */ 213 { { 0xFF, 0x10 }, 2 }, 214 /* VBP+VSA=,VFP = 10H */ 215 { { 0x3B, 0x03, 0x0A, 0x0A }, 4 }, 216 /* FTE on */ 217 { { 0x35, 0x00 }, 2 }, 218 /* EN_BK =1(auto black) */ 219 { { 0xE5, 0x01 }, 2 }, 220 /* CMD mode(10) VDO mode(03) */ 221 { { 0xBB, 0x03 }, 2 }, 222 /* Non Reload MTP */ 223 { { 0xFB, 0x01 }, 2 }, 224 }; 225 226 static int truly_dcs_write(struct drm_panel *panel, u32 command) 227 { 228 struct truly_nt35597 *ctx = panel_to_ctx(panel); 229 int i, ret; 230 231 for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) { 232 ret = mipi_dsi_dcs_write(ctx->dsi[i], command, NULL, 0); 233 if (ret < 0) { 234 DRM_DEV_ERROR(ctx->dev, 235 "cmd 0x%x failed for dsi = %d\n", 236 command, i); 237 } 238 } 239 240 return ret; 241 } 242 243 static int truly_dcs_write_buf(struct drm_panel *panel, 244 u32 size, const u8 *buf) 245 { 246 struct truly_nt35597 *ctx = panel_to_ctx(panel); 247 int ret = 0; 248 int i; 249 250 for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) { 251 ret = mipi_dsi_dcs_write_buffer(ctx->dsi[i], buf, size); 252 if (ret < 0) { 253 DRM_DEV_ERROR(ctx->dev, 254 "failed to tx cmd [%d], err: %d\n", i, ret); 255 return ret; 256 } 257 } 258 259 return ret; 260 } 261 262 static int truly_35597_power_on(struct truly_nt35597 *ctx) 263 { 264 int ret, i; 265 266 for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) { 267 ret = regulator_set_load(ctx->supplies[i].consumer, 268 regulator_enable_loads[i]); 269 if (ret) 270 return ret; 271 } 272 273 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 274 if (ret < 0) 275 return ret; 276 277 /* 278 * Reset sequence of truly panel requires the panel to be 279 * out of reset for 10ms, followed by being held in reset 280 * for 10ms and then out again 281 */ 282 gpiod_set_value(ctx->reset_gpio, 0); 283 usleep_range(10000, 20000); 284 gpiod_set_value(ctx->reset_gpio, 1); 285 usleep_range(10000, 20000); 286 gpiod_set_value(ctx->reset_gpio, 0); 287 usleep_range(10000, 20000); 288 289 return 0; 290 } 291 292 static int truly_nt35597_power_off(struct truly_nt35597 *ctx) 293 { 294 int ret = 0; 295 int i; 296 297 gpiod_set_value(ctx->reset_gpio, 1); 298 299 for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) { 300 ret = regulator_set_load(ctx->supplies[i].consumer, 301 regulator_disable_loads[i]); 302 if (ret) { 303 DRM_DEV_ERROR(ctx->dev, 304 "regulator_set_load failed %d\n", ret); 305 return ret; 306 } 307 } 308 309 ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 310 if (ret) { 311 DRM_DEV_ERROR(ctx->dev, 312 "regulator_bulk_disable failed %d\n", ret); 313 } 314 return ret; 315 } 316 317 static int truly_nt35597_disable(struct drm_panel *panel) 318 { 319 struct truly_nt35597 *ctx = panel_to_ctx(panel); 320 int ret; 321 322 if (!ctx->enabled) 323 return 0; 324 325 if (ctx->backlight) { 326 ret = backlight_disable(ctx->backlight); 327 if (ret < 0) 328 DRM_DEV_ERROR(ctx->dev, "backlight disable failed %d\n", 329 ret); 330 } 331 332 ctx->enabled = false; 333 return 0; 334 } 335 336 static int truly_nt35597_unprepare(struct drm_panel *panel) 337 { 338 struct truly_nt35597 *ctx = panel_to_ctx(panel); 339 int ret = 0; 340 341 if (!ctx->prepared) 342 return 0; 343 344 ctx->dsi[0]->mode_flags = 0; 345 ctx->dsi[1]->mode_flags = 0; 346 347 ret = truly_dcs_write(panel, MIPI_DCS_SET_DISPLAY_OFF); 348 if (ret < 0) { 349 DRM_DEV_ERROR(ctx->dev, 350 "set_display_off cmd failed ret = %d\n", 351 ret); 352 } 353 354 /* 120ms delay required here as per DCS spec */ 355 msleep(120); 356 357 ret = truly_dcs_write(panel, MIPI_DCS_ENTER_SLEEP_MODE); 358 if (ret < 0) { 359 DRM_DEV_ERROR(ctx->dev, 360 "enter_sleep cmd failed ret = %d\n", ret); 361 } 362 363 ret = truly_nt35597_power_off(ctx); 364 if (ret < 0) 365 DRM_DEV_ERROR(ctx->dev, "power_off failed ret = %d\n", ret); 366 367 ctx->prepared = false; 368 return ret; 369 } 370 371 static int truly_nt35597_prepare(struct drm_panel *panel) 372 { 373 struct truly_nt35597 *ctx = panel_to_ctx(panel); 374 int ret; 375 int i; 376 const struct cmd_set *panel_on_cmds; 377 const struct nt35597_config *config; 378 u32 num_cmds; 379 380 if (ctx->prepared) 381 return 0; 382 383 ret = truly_35597_power_on(ctx); 384 if (ret < 0) 385 return ret; 386 387 ctx->dsi[0]->mode_flags |= MIPI_DSI_MODE_LPM; 388 ctx->dsi[1]->mode_flags |= MIPI_DSI_MODE_LPM; 389 390 config = ctx->config; 391 panel_on_cmds = config->panel_on_cmds; 392 num_cmds = config->num_on_cmds; 393 394 for (i = 0; i < num_cmds; i++) { 395 ret = truly_dcs_write_buf(panel, 396 panel_on_cmds[i].size, 397 panel_on_cmds[i].commands); 398 if (ret < 0) { 399 DRM_DEV_ERROR(ctx->dev, 400 "cmd set tx failed i = %d ret = %d\n", 401 i, ret); 402 goto power_off; 403 } 404 } 405 406 ret = truly_dcs_write(panel, MIPI_DCS_EXIT_SLEEP_MODE); 407 if (ret < 0) { 408 DRM_DEV_ERROR(ctx->dev, 409 "exit_sleep_mode cmd failed ret = %d\n", 410 ret); 411 goto power_off; 412 } 413 414 /* Per DSI spec wait 120ms after sending exit sleep DCS command */ 415 msleep(120); 416 417 ret = truly_dcs_write(panel, MIPI_DCS_SET_DISPLAY_ON); 418 if (ret < 0) { 419 DRM_DEV_ERROR(ctx->dev, 420 "set_display_on cmd failed ret = %d\n", ret); 421 goto power_off; 422 } 423 424 /* Per DSI spec wait 120ms after sending set_display_on DCS command */ 425 msleep(120); 426 427 ctx->prepared = true; 428 429 return 0; 430 431 power_off: 432 if (truly_nt35597_power_off(ctx)) 433 DRM_DEV_ERROR(ctx->dev, "power_off failed\n"); 434 return ret; 435 } 436 437 static int truly_nt35597_enable(struct drm_panel *panel) 438 { 439 struct truly_nt35597 *ctx = panel_to_ctx(panel); 440 int ret; 441 442 if (ctx->enabled) 443 return 0; 444 445 if (ctx->backlight) { 446 ret = backlight_enable(ctx->backlight); 447 if (ret < 0) 448 DRM_DEV_ERROR(ctx->dev, "backlight enable failed %d\n", 449 ret); 450 } 451 452 ctx->enabled = true; 453 454 return 0; 455 } 456 457 static int truly_nt35597_get_modes(struct drm_panel *panel, 458 struct drm_connector *connector) 459 { 460 struct truly_nt35597 *ctx = panel_to_ctx(panel); 461 struct drm_display_mode *mode; 462 const struct nt35597_config *config; 463 464 config = ctx->config; 465 mode = drm_mode_create(connector->dev); 466 if (!mode) { 467 DRM_DEV_ERROR(ctx->dev, 468 "failed to create a new display mode\n"); 469 return 0; 470 } 471 472 connector->display_info.width_mm = config->width_mm; 473 connector->display_info.height_mm = config->height_mm; 474 drm_mode_copy(mode, config->dm); 475 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 476 drm_mode_probed_add(connector, mode); 477 478 return 1; 479 } 480 481 static const struct drm_panel_funcs truly_nt35597_drm_funcs = { 482 .disable = truly_nt35597_disable, 483 .unprepare = truly_nt35597_unprepare, 484 .prepare = truly_nt35597_prepare, 485 .enable = truly_nt35597_enable, 486 .get_modes = truly_nt35597_get_modes, 487 }; 488 489 static int truly_nt35597_panel_add(struct truly_nt35597 *ctx) 490 { 491 struct device *dev = ctx->dev; 492 int ret, i; 493 const struct nt35597_config *config; 494 495 config = ctx->config; 496 for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) 497 ctx->supplies[i].supply = regulator_names[i]; 498 499 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 500 ctx->supplies); 501 if (ret < 0) 502 return ret; 503 504 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 505 if (IS_ERR(ctx->reset_gpio)) { 506 DRM_DEV_ERROR(dev, "cannot get reset gpio %ld\n", 507 PTR_ERR(ctx->reset_gpio)); 508 return PTR_ERR(ctx->reset_gpio); 509 } 510 511 ctx->mode_gpio = devm_gpiod_get(dev, "mode", GPIOD_OUT_LOW); 512 if (IS_ERR(ctx->mode_gpio)) { 513 DRM_DEV_ERROR(dev, "cannot get mode gpio %ld\n", 514 PTR_ERR(ctx->mode_gpio)); 515 return PTR_ERR(ctx->mode_gpio); 516 } 517 518 /* dual port */ 519 gpiod_set_value(ctx->mode_gpio, 0); 520 521 drm_panel_init(&ctx->panel, dev, &truly_nt35597_drm_funcs, 522 DRM_MODE_CONNECTOR_DSI); 523 drm_panel_add(&ctx->panel); 524 525 return 0; 526 } 527 528 static const struct drm_display_mode qcom_sdm845_mtp_2k_mode = { 529 .name = "1440x2560", 530 .clock = 268316, 531 .hdisplay = 1440, 532 .hsync_start = 1440 + 200, 533 .hsync_end = 1440 + 200 + 32, 534 .htotal = 1440 + 200 + 32 + 64, 535 .vdisplay = 2560, 536 .vsync_start = 2560 + 8, 537 .vsync_end = 2560 + 8 + 1, 538 .vtotal = 2560 + 8 + 1 + 7, 539 .vrefresh = 60, 540 .flags = 0, 541 }; 542 543 static const struct nt35597_config nt35597_dir = { 544 .width_mm = 74, 545 .height_mm = 131, 546 .panel_name = "qcom_sdm845_mtp_2k_panel", 547 .dm = &qcom_sdm845_mtp_2k_mode, 548 .panel_on_cmds = qcom_2k_panel_magic_cmds, 549 .num_on_cmds = ARRAY_SIZE(qcom_2k_panel_magic_cmds), 550 }; 551 552 static int truly_nt35597_probe(struct mipi_dsi_device *dsi) 553 { 554 struct device *dev = &dsi->dev; 555 struct truly_nt35597 *ctx; 556 struct mipi_dsi_device *dsi1_device; 557 struct device_node *dsi1; 558 struct mipi_dsi_host *dsi1_host; 559 struct mipi_dsi_device *dsi_dev; 560 int ret = 0; 561 int i; 562 563 const struct mipi_dsi_device_info info = { 564 .type = "trulynt35597", 565 .channel = 0, 566 .node = NULL, 567 }; 568 569 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 570 571 if (!ctx) 572 return -ENOMEM; 573 574 /* 575 * This device represents itself as one with two input ports which are 576 * fed by the output ports of the two DSI controllers . The DSI0 is 577 * the master controller and has most of the panel related info in its 578 * child node. 579 */ 580 581 ctx->config = of_device_get_match_data(dev); 582 583 if (!ctx->config) { 584 dev_err(dev, "missing device configuration\n"); 585 return -ENODEV; 586 } 587 588 dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1); 589 if (!dsi1) { 590 DRM_DEV_ERROR(dev, 591 "failed to get remote node for dsi1_device\n"); 592 return -ENODEV; 593 } 594 595 dsi1_host = of_find_mipi_dsi_host_by_node(dsi1); 596 of_node_put(dsi1); 597 if (!dsi1_host) { 598 DRM_DEV_ERROR(dev, "failed to find dsi host\n"); 599 return -EPROBE_DEFER; 600 } 601 602 /* register the second DSI device */ 603 dsi1_device = mipi_dsi_device_register_full(dsi1_host, &info); 604 if (IS_ERR(dsi1_device)) { 605 DRM_DEV_ERROR(dev, "failed to create dsi device\n"); 606 return PTR_ERR(dsi1_device); 607 } 608 609 mipi_dsi_set_drvdata(dsi, ctx); 610 611 ctx->dev = dev; 612 ctx->dsi[0] = dsi; 613 ctx->dsi[1] = dsi1_device; 614 615 ret = truly_nt35597_panel_add(ctx); 616 if (ret) { 617 DRM_DEV_ERROR(dev, "failed to add panel\n"); 618 goto err_panel_add; 619 } 620 621 for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) { 622 dsi_dev = ctx->dsi[i]; 623 dsi_dev->lanes = 4; 624 dsi_dev->format = MIPI_DSI_FMT_RGB888; 625 dsi_dev->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | 626 MIPI_DSI_CLOCK_NON_CONTINUOUS; 627 ret = mipi_dsi_attach(dsi_dev); 628 if (ret < 0) { 629 DRM_DEV_ERROR(dev, 630 "dsi attach failed i = %d\n", i); 631 goto err_dsi_attach; 632 } 633 } 634 635 return 0; 636 637 err_dsi_attach: 638 drm_panel_remove(&ctx->panel); 639 err_panel_add: 640 mipi_dsi_device_unregister(dsi1_device); 641 return ret; 642 } 643 644 static int truly_nt35597_remove(struct mipi_dsi_device *dsi) 645 { 646 struct truly_nt35597 *ctx = mipi_dsi_get_drvdata(dsi); 647 648 if (ctx->dsi[0]) 649 mipi_dsi_detach(ctx->dsi[0]); 650 if (ctx->dsi[1]) { 651 mipi_dsi_detach(ctx->dsi[1]); 652 mipi_dsi_device_unregister(ctx->dsi[1]); 653 } 654 655 drm_panel_remove(&ctx->panel); 656 return 0; 657 } 658 659 static const struct of_device_id truly_nt35597_of_match[] = { 660 { 661 .compatible = "truly,nt35597-2K-display", 662 .data = &nt35597_dir, 663 }, 664 { } 665 }; 666 MODULE_DEVICE_TABLE(of, truly_nt35597_of_match); 667 668 static struct mipi_dsi_driver truly_nt35597_driver = { 669 .driver = { 670 .name = "panel-truly-nt35597", 671 .of_match_table = truly_nt35597_of_match, 672 }, 673 .probe = truly_nt35597_probe, 674 .remove = truly_nt35597_remove, 675 }; 676 module_mipi_dsi_driver(truly_nt35597_driver); 677 678 MODULE_DESCRIPTION("Truly NT35597 DSI Panel Driver"); 679 MODULE_LICENSE("GPL v2"); 680