1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * R-Car Display Unit DRM driver 4 * 5 * Copyright (C) 2013-2015 Renesas Electronics Corporation 6 * 7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/dma-mapping.h> 12 #include <linux/io.h> 13 #include <linux/mm.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 #include <linux/pm.h> 18 #include <linux/slab.h> 19 #include <linux/wait.h> 20 21 #include <drm/clients/drm_client_setup.h> 22 #include <drm/drm_atomic_helper.h> 23 #include <drm/drm_drv.h> 24 #include <drm/drm_fbdev_dma.h> 25 #include <drm/drm_gem_dma_helper.h> 26 #include <drm/drm_managed.h> 27 #include <drm/drm_print.h> 28 #include <drm/drm_probe_helper.h> 29 30 #include "rcar_du_drv.h" 31 #include "rcar_du_kms.h" 32 33 /* ----------------------------------------------------------------------------- 34 * Device Information 35 */ 36 37 static const struct rcar_du_device_info rzg1_du_r8a7743_info = { 38 .gen = 2, 39 .features = RCAR_DU_FEATURE_CRTC_IRQ 40 | RCAR_DU_FEATURE_CRTC_CLOCK 41 | RCAR_DU_FEATURE_INTERLACED 42 | RCAR_DU_FEATURE_TVM_SYNC, 43 .channels_mask = BIT(1) | BIT(0), 44 .routes = { 45 /* 46 * R8A774[34] has one RGB output and one LVDS output 47 */ 48 [RCAR_DU_OUTPUT_DPAD0] = { 49 .possible_crtcs = BIT(1) | BIT(0), 50 .port = 0, 51 }, 52 [RCAR_DU_OUTPUT_LVDS0] = { 53 .possible_crtcs = BIT(0), 54 .port = 1, 55 }, 56 }, 57 .num_lvds = 1, 58 .num_rpf = 4, 59 }; 60 61 static const struct rcar_du_device_info rzg1_du_r8a7745_info = { 62 .gen = 2, 63 .features = RCAR_DU_FEATURE_CRTC_IRQ 64 | RCAR_DU_FEATURE_CRTC_CLOCK 65 | RCAR_DU_FEATURE_INTERLACED 66 | RCAR_DU_FEATURE_TVM_SYNC, 67 .channels_mask = BIT(1) | BIT(0), 68 .routes = { 69 /* 70 * R8A7745 has two RGB outputs 71 */ 72 [RCAR_DU_OUTPUT_DPAD0] = { 73 .possible_crtcs = BIT(0), 74 .port = 0, 75 }, 76 [RCAR_DU_OUTPUT_DPAD1] = { 77 .possible_crtcs = BIT(1), 78 .port = 1, 79 }, 80 }, 81 .num_rpf = 4, 82 }; 83 84 static const struct rcar_du_device_info rzg1_du_r8a77470_info = { 85 .gen = 2, 86 .features = RCAR_DU_FEATURE_CRTC_IRQ 87 | RCAR_DU_FEATURE_CRTC_CLOCK 88 | RCAR_DU_FEATURE_INTERLACED 89 | RCAR_DU_FEATURE_TVM_SYNC, 90 .channels_mask = BIT(1) | BIT(0), 91 .routes = { 92 /* 93 * R8A77470 has two RGB outputs, one LVDS output, and 94 * one (currently unsupported) analog video output 95 */ 96 [RCAR_DU_OUTPUT_DPAD0] = { 97 .possible_crtcs = BIT(0), 98 .port = 0, 99 }, 100 [RCAR_DU_OUTPUT_DPAD1] = { 101 .possible_crtcs = BIT(1), 102 .port = 1, 103 }, 104 [RCAR_DU_OUTPUT_LVDS0] = { 105 .possible_crtcs = BIT(0) | BIT(1), 106 .port = 2, 107 }, 108 }, 109 .num_rpf = 4, 110 }; 111 112 static const struct rcar_du_device_info rcar_du_r8a774a1_info = { 113 .gen = 3, 114 .features = RCAR_DU_FEATURE_CRTC_IRQ 115 | RCAR_DU_FEATURE_CRTC_CLOCK 116 | RCAR_DU_FEATURE_VSP1_SOURCE 117 | RCAR_DU_FEATURE_INTERLACED 118 | RCAR_DU_FEATURE_TVM_SYNC, 119 .channels_mask = BIT(2) | BIT(1) | BIT(0), 120 .routes = { 121 /* 122 * R8A774A1 has one RGB output, one LVDS output and one HDMI 123 * output. 124 */ 125 [RCAR_DU_OUTPUT_DPAD0] = { 126 .possible_crtcs = BIT(2), 127 .port = 0, 128 }, 129 [RCAR_DU_OUTPUT_HDMI0] = { 130 .possible_crtcs = BIT(1), 131 .port = 1, 132 }, 133 [RCAR_DU_OUTPUT_LVDS0] = { 134 .possible_crtcs = BIT(0), 135 .port = 2, 136 }, 137 }, 138 .num_lvds = 1, 139 .num_rpf = 5, 140 .dpll_mask = BIT(1), 141 }; 142 143 static const struct rcar_du_device_info rcar_du_r8a774b1_info = { 144 .gen = 3, 145 .features = RCAR_DU_FEATURE_CRTC_IRQ 146 | RCAR_DU_FEATURE_CRTC_CLOCK 147 | RCAR_DU_FEATURE_VSP1_SOURCE 148 | RCAR_DU_FEATURE_INTERLACED 149 | RCAR_DU_FEATURE_TVM_SYNC, 150 .channels_mask = BIT(3) | BIT(1) | BIT(0), 151 .routes = { 152 /* 153 * R8A774B1 has one RGB output, one LVDS output and one HDMI 154 * output. 155 */ 156 [RCAR_DU_OUTPUT_DPAD0] = { 157 .possible_crtcs = BIT(2), 158 .port = 0, 159 }, 160 [RCAR_DU_OUTPUT_HDMI0] = { 161 .possible_crtcs = BIT(1), 162 .port = 1, 163 }, 164 [RCAR_DU_OUTPUT_LVDS0] = { 165 .possible_crtcs = BIT(0), 166 .port = 2, 167 }, 168 }, 169 .num_lvds = 1, 170 .num_rpf = 5, 171 .dpll_mask = BIT(1), 172 }; 173 174 static const struct rcar_du_device_info rcar_du_r8a774c0_info = { 175 .gen = 3, 176 .features = RCAR_DU_FEATURE_CRTC_IRQ 177 | RCAR_DU_FEATURE_CRTC_CLOCK 178 | RCAR_DU_FEATURE_VSP1_SOURCE, 179 .channels_mask = BIT(1) | BIT(0), 180 .routes = { 181 /* 182 * R8A774C0 has one RGB output and two LVDS outputs 183 */ 184 [RCAR_DU_OUTPUT_DPAD0] = { 185 .possible_crtcs = BIT(0) | BIT(1), 186 .port = 0, 187 }, 188 [RCAR_DU_OUTPUT_LVDS0] = { 189 .possible_crtcs = BIT(0), 190 .port = 1, 191 }, 192 [RCAR_DU_OUTPUT_LVDS1] = { 193 .possible_crtcs = BIT(1), 194 .port = 2, 195 }, 196 }, 197 .num_lvds = 2, 198 .num_rpf = 4, 199 .lvds_clk_mask = BIT(1) | BIT(0), 200 }; 201 202 static const struct rcar_du_device_info rcar_du_r8a774e1_info = { 203 .gen = 3, 204 .features = RCAR_DU_FEATURE_CRTC_IRQ 205 | RCAR_DU_FEATURE_CRTC_CLOCK 206 | RCAR_DU_FEATURE_VSP1_SOURCE 207 | RCAR_DU_FEATURE_INTERLACED 208 | RCAR_DU_FEATURE_TVM_SYNC, 209 .channels_mask = BIT(3) | BIT(1) | BIT(0), 210 .routes = { 211 /* 212 * R8A774E1 has one RGB output, one LVDS output and one HDMI 213 * output. 214 */ 215 [RCAR_DU_OUTPUT_DPAD0] = { 216 .possible_crtcs = BIT(2), 217 .port = 0, 218 }, 219 [RCAR_DU_OUTPUT_HDMI0] = { 220 .possible_crtcs = BIT(1), 221 .port = 1, 222 }, 223 [RCAR_DU_OUTPUT_LVDS0] = { 224 .possible_crtcs = BIT(0), 225 .port = 2, 226 }, 227 }, 228 .num_lvds = 1, 229 .num_rpf = 5, 230 .dpll_mask = BIT(1), 231 }; 232 233 static const struct rcar_du_device_info rcar_du_r8a7779_info = { 234 .gen = 1, 235 .features = RCAR_DU_FEATURE_INTERLACED 236 | RCAR_DU_FEATURE_TVM_SYNC, 237 .channels_mask = BIT(1) | BIT(0), 238 .routes = { 239 /* 240 * R8A7779 has two RGB outputs and one (currently unsupported) 241 * TCON output. 242 */ 243 [RCAR_DU_OUTPUT_DPAD0] = { 244 .possible_crtcs = BIT(0), 245 .port = 0, 246 }, 247 [RCAR_DU_OUTPUT_DPAD1] = { 248 .possible_crtcs = BIT(1) | BIT(0), 249 .port = 1, 250 }, 251 }, 252 }; 253 254 static const struct rcar_du_device_info rcar_du_r8a7790_info = { 255 .gen = 2, 256 .features = RCAR_DU_FEATURE_CRTC_IRQ 257 | RCAR_DU_FEATURE_CRTC_CLOCK 258 | RCAR_DU_FEATURE_INTERLACED 259 | RCAR_DU_FEATURE_TVM_SYNC, 260 .quirks = RCAR_DU_QUIRK_ALIGN_128B, 261 .channels_mask = BIT(2) | BIT(1) | BIT(0), 262 .routes = { 263 /* 264 * R8A7742 and R8A7790 each have one RGB output and two LVDS 265 * outputs. Additionally R8A7790 supports one TCON output 266 * (currently unsupported by the driver). 267 */ 268 [RCAR_DU_OUTPUT_DPAD0] = { 269 .possible_crtcs = BIT(2) | BIT(1) | BIT(0), 270 .port = 0, 271 }, 272 [RCAR_DU_OUTPUT_LVDS0] = { 273 .possible_crtcs = BIT(0), 274 .port = 1, 275 }, 276 [RCAR_DU_OUTPUT_LVDS1] = { 277 .possible_crtcs = BIT(2) | BIT(1), 278 .port = 2, 279 }, 280 }, 281 .num_lvds = 2, 282 .num_rpf = 4, 283 }; 284 285 /* M2-W (r8a7791) and M2-N (r8a7793) are identical */ 286 static const struct rcar_du_device_info rcar_du_r8a7791_info = { 287 .gen = 2, 288 .features = RCAR_DU_FEATURE_CRTC_IRQ 289 | RCAR_DU_FEATURE_CRTC_CLOCK 290 | RCAR_DU_FEATURE_INTERLACED 291 | RCAR_DU_FEATURE_TVM_SYNC, 292 .channels_mask = BIT(1) | BIT(0), 293 .routes = { 294 /* 295 * R8A779[13] has one RGB output, one LVDS output and one 296 * (currently unsupported) TCON output. 297 */ 298 [RCAR_DU_OUTPUT_DPAD0] = { 299 .possible_crtcs = BIT(1) | BIT(0), 300 .port = 0, 301 }, 302 [RCAR_DU_OUTPUT_LVDS0] = { 303 .possible_crtcs = BIT(0), 304 .port = 1, 305 }, 306 }, 307 .num_lvds = 1, 308 .num_rpf = 4, 309 }; 310 311 static const struct rcar_du_device_info rcar_du_r8a7792_info = { 312 .gen = 2, 313 .features = RCAR_DU_FEATURE_CRTC_IRQ 314 | RCAR_DU_FEATURE_CRTC_CLOCK 315 | RCAR_DU_FEATURE_INTERLACED 316 | RCAR_DU_FEATURE_TVM_SYNC, 317 .channels_mask = BIT(1) | BIT(0), 318 .routes = { 319 /* R8A7792 has two RGB outputs. */ 320 [RCAR_DU_OUTPUT_DPAD0] = { 321 .possible_crtcs = BIT(0), 322 .port = 0, 323 }, 324 [RCAR_DU_OUTPUT_DPAD1] = { 325 .possible_crtcs = BIT(1), 326 .port = 1, 327 }, 328 }, 329 .num_rpf = 4, 330 }; 331 332 static const struct rcar_du_device_info rcar_du_r8a7794_info = { 333 .gen = 2, 334 .features = RCAR_DU_FEATURE_CRTC_IRQ 335 | RCAR_DU_FEATURE_CRTC_CLOCK 336 | RCAR_DU_FEATURE_INTERLACED 337 | RCAR_DU_FEATURE_TVM_SYNC, 338 .channels_mask = BIT(1) | BIT(0), 339 .routes = { 340 /* 341 * R8A7794 has two RGB outputs and one (currently unsupported) 342 * TCON output. 343 */ 344 [RCAR_DU_OUTPUT_DPAD0] = { 345 .possible_crtcs = BIT(0), 346 .port = 0, 347 }, 348 [RCAR_DU_OUTPUT_DPAD1] = { 349 .possible_crtcs = BIT(1), 350 .port = 1, 351 }, 352 }, 353 .num_rpf = 4, 354 }; 355 356 static const struct rcar_du_device_info rcar_du_r8a7795_info = { 357 .gen = 3, 358 .features = RCAR_DU_FEATURE_CRTC_IRQ 359 | RCAR_DU_FEATURE_CRTC_CLOCK 360 | RCAR_DU_FEATURE_VSP1_SOURCE 361 | RCAR_DU_FEATURE_INTERLACED 362 | RCAR_DU_FEATURE_TVM_SYNC, 363 .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0), 364 .routes = { 365 /* 366 * R8A7795 has one RGB output, two HDMI outputs and one 367 * LVDS output. 368 */ 369 [RCAR_DU_OUTPUT_DPAD0] = { 370 .possible_crtcs = BIT(3), 371 .port = 0, 372 }, 373 [RCAR_DU_OUTPUT_HDMI0] = { 374 .possible_crtcs = BIT(1), 375 .port = 1, 376 }, 377 [RCAR_DU_OUTPUT_HDMI1] = { 378 .possible_crtcs = BIT(2), 379 .port = 2, 380 }, 381 [RCAR_DU_OUTPUT_LVDS0] = { 382 .possible_crtcs = BIT(0), 383 .port = 3, 384 }, 385 }, 386 .num_lvds = 1, 387 .num_rpf = 5, 388 .dpll_mask = BIT(2) | BIT(1), 389 }; 390 391 static const struct rcar_du_device_info rcar_du_r8a7796_info = { 392 .gen = 3, 393 .features = RCAR_DU_FEATURE_CRTC_IRQ 394 | RCAR_DU_FEATURE_CRTC_CLOCK 395 | RCAR_DU_FEATURE_VSP1_SOURCE 396 | RCAR_DU_FEATURE_INTERLACED 397 | RCAR_DU_FEATURE_TVM_SYNC, 398 .channels_mask = BIT(2) | BIT(1) | BIT(0), 399 .routes = { 400 /* 401 * R8A7796 has one RGB output, one LVDS output and one HDMI 402 * output. 403 */ 404 [RCAR_DU_OUTPUT_DPAD0] = { 405 .possible_crtcs = BIT(2), 406 .port = 0, 407 }, 408 [RCAR_DU_OUTPUT_HDMI0] = { 409 .possible_crtcs = BIT(1), 410 .port = 1, 411 }, 412 [RCAR_DU_OUTPUT_LVDS0] = { 413 .possible_crtcs = BIT(0), 414 .port = 2, 415 }, 416 }, 417 .num_lvds = 1, 418 .num_rpf = 5, 419 .dpll_mask = BIT(1), 420 }; 421 422 static const struct rcar_du_device_info rcar_du_r8a77965_info = { 423 .gen = 3, 424 .features = RCAR_DU_FEATURE_CRTC_IRQ 425 | RCAR_DU_FEATURE_CRTC_CLOCK 426 | RCAR_DU_FEATURE_VSP1_SOURCE 427 | RCAR_DU_FEATURE_INTERLACED 428 | RCAR_DU_FEATURE_TVM_SYNC, 429 .channels_mask = BIT(3) | BIT(1) | BIT(0), 430 .routes = { 431 /* 432 * R8A77965 has one RGB output, one LVDS output and one HDMI 433 * output. 434 */ 435 [RCAR_DU_OUTPUT_DPAD0] = { 436 .possible_crtcs = BIT(2), 437 .port = 0, 438 }, 439 [RCAR_DU_OUTPUT_HDMI0] = { 440 .possible_crtcs = BIT(1), 441 .port = 1, 442 }, 443 [RCAR_DU_OUTPUT_LVDS0] = { 444 .possible_crtcs = BIT(0), 445 .port = 2, 446 }, 447 }, 448 .num_lvds = 1, 449 .num_rpf = 5, 450 .dpll_mask = BIT(1), 451 }; 452 453 static const struct rcar_du_device_info rcar_du_r8a77970_info = { 454 .gen = 3, 455 .features = RCAR_DU_FEATURE_CRTC_IRQ 456 | RCAR_DU_FEATURE_CRTC_CLOCK 457 | RCAR_DU_FEATURE_VSP1_SOURCE 458 | RCAR_DU_FEATURE_INTERLACED 459 | RCAR_DU_FEATURE_TVM_SYNC, 460 .channels_mask = BIT(0), 461 .routes = { 462 /* 463 * R8A77970 and R8A77980 have one RGB output and one LVDS 464 * output. 465 */ 466 [RCAR_DU_OUTPUT_DPAD0] = { 467 .possible_crtcs = BIT(0), 468 .port = 0, 469 }, 470 [RCAR_DU_OUTPUT_LVDS0] = { 471 .possible_crtcs = BIT(0), 472 .port = 1, 473 }, 474 }, 475 .num_lvds = 1, 476 .num_rpf = 5, 477 }; 478 479 static const struct rcar_du_device_info rcar_du_r8a7799x_info = { 480 .gen = 3, 481 .features = RCAR_DU_FEATURE_CRTC_IRQ 482 | RCAR_DU_FEATURE_CRTC_CLOCK 483 | RCAR_DU_FEATURE_VSP1_SOURCE, 484 .channels_mask = BIT(1) | BIT(0), 485 .routes = { 486 /* 487 * R8A77990 and R8A77995 have one RGB output and two LVDS 488 * outputs. 489 */ 490 [RCAR_DU_OUTPUT_DPAD0] = { 491 .possible_crtcs = BIT(0) | BIT(1), 492 .port = 0, 493 }, 494 [RCAR_DU_OUTPUT_LVDS0] = { 495 .possible_crtcs = BIT(0), 496 .port = 1, 497 }, 498 [RCAR_DU_OUTPUT_LVDS1] = { 499 .possible_crtcs = BIT(1), 500 .port = 2, 501 }, 502 }, 503 .num_lvds = 2, 504 .num_rpf = 5, 505 .lvds_clk_mask = BIT(1) | BIT(0), 506 }; 507 508 static const struct rcar_du_device_info rcar_du_r8a779a0_info = { 509 .gen = 4, 510 .features = RCAR_DU_FEATURE_CRTC_IRQ 511 | RCAR_DU_FEATURE_VSP1_SOURCE 512 | RCAR_DU_FEATURE_NO_BLENDING, 513 .channels_mask = BIT(1) | BIT(0), 514 .routes = { 515 /* R8A779A0 has two MIPI DSI outputs. */ 516 [RCAR_DU_OUTPUT_DSI0] = { 517 .possible_crtcs = BIT(0), 518 .port = 0, 519 }, 520 [RCAR_DU_OUTPUT_DSI1] = { 521 .possible_crtcs = BIT(1), 522 .port = 1, 523 }, 524 }, 525 .num_rpf = 5, 526 .dsi_clk_mask = BIT(1) | BIT(0), 527 }; 528 529 static const struct rcar_du_device_info rcar_du_r8a779g0_info = { 530 .gen = 4, 531 .features = RCAR_DU_FEATURE_CRTC_IRQ 532 | RCAR_DU_FEATURE_VSP1_SOURCE 533 | RCAR_DU_FEATURE_NO_BLENDING, 534 .channels_mask = BIT(1) | BIT(0), 535 .routes = { 536 /* R8A779G0 has two MIPI DSI outputs. */ 537 [RCAR_DU_OUTPUT_DSI0] = { 538 .possible_crtcs = BIT(0), 539 .port = 0, 540 }, 541 [RCAR_DU_OUTPUT_DSI1] = { 542 .possible_crtcs = BIT(1), 543 .port = 1, 544 }, 545 }, 546 .num_rpf = 5, 547 .dsi_clk_mask = BIT(1) | BIT(0), 548 }; 549 550 static const struct rcar_du_device_info rcar_du_r8a779h0_info = { 551 .gen = 4, 552 .features = RCAR_DU_FEATURE_CRTC_IRQ 553 | RCAR_DU_FEATURE_VSP1_SOURCE 554 | RCAR_DU_FEATURE_NO_BLENDING, 555 .channels_mask = BIT(0), 556 .routes = { 557 /* R8A779H0 has one MIPI DSI output. */ 558 [RCAR_DU_OUTPUT_DSI0] = { 559 .possible_crtcs = BIT(0), 560 .port = 0, 561 }, 562 }, 563 .num_rpf = 5, 564 .dsi_clk_mask = BIT(0), 565 }; 566 567 static const struct of_device_id rcar_du_of_table[] = { 568 { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info }, 569 { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info }, 570 { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info }, 571 { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info }, 572 { .compatible = "renesas,du-r8a77470", .data = &rzg1_du_r8a77470_info }, 573 { .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info }, 574 { .compatible = "renesas,du-r8a774b1", .data = &rcar_du_r8a774b1_info }, 575 { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info }, 576 { .compatible = "renesas,du-r8a774e1", .data = &rcar_du_r8a774e1_info }, 577 { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info }, 578 { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info }, 579 { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info }, 580 { .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info }, 581 { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info }, 582 { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info }, 583 { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, 584 { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, 585 { .compatible = "renesas,du-r8a77961", .data = &rcar_du_r8a7796_info }, 586 { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, 587 { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info }, 588 { .compatible = "renesas,du-r8a77980", .data = &rcar_du_r8a77970_info }, 589 { .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info }, 590 { .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info }, 591 { .compatible = "renesas,du-r8a779a0", .data = &rcar_du_r8a779a0_info }, 592 { .compatible = "renesas,du-r8a779g0", .data = &rcar_du_r8a779g0_info }, 593 { .compatible = "renesas,du-r8a779h0", .data = &rcar_du_r8a779h0_info }, 594 { } 595 }; 596 597 MODULE_DEVICE_TABLE(of, rcar_du_of_table); 598 599 const char *rcar_du_output_name(enum rcar_du_output output) 600 { 601 static const char * const names[] = { 602 [RCAR_DU_OUTPUT_DPAD0] = "DPAD0", 603 [RCAR_DU_OUTPUT_DPAD1] = "DPAD1", 604 [RCAR_DU_OUTPUT_DSI0] = "DSI0", 605 [RCAR_DU_OUTPUT_DSI1] = "DSI1", 606 [RCAR_DU_OUTPUT_HDMI0] = "HDMI0", 607 [RCAR_DU_OUTPUT_HDMI1] = "HDMI1", 608 [RCAR_DU_OUTPUT_LVDS0] = "LVDS0", 609 [RCAR_DU_OUTPUT_LVDS1] = "LVDS1", 610 [RCAR_DU_OUTPUT_TCON] = "TCON", 611 }; 612 613 if (output >= ARRAY_SIZE(names) || !names[output]) 614 return "UNKNOWN"; 615 616 return names[output]; 617 } 618 619 /* ----------------------------------------------------------------------------- 620 * DRM operations 621 */ 622 623 DEFINE_DRM_GEM_DMA_FOPS(rcar_du_fops); 624 625 static const struct drm_driver rcar_du_driver = { 626 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, 627 .dumb_create = rcar_du_dumb_create, 628 .gem_prime_import_sg_table = rcar_du_gem_prime_import_sg_table, 629 DRM_FBDEV_DMA_DRIVER_OPS, 630 .fops = &rcar_du_fops, 631 .name = "rcar-du", 632 .desc = "Renesas R-Car Display Unit", 633 .major = 1, 634 .minor = 0, 635 }; 636 637 /* ----------------------------------------------------------------------------- 638 * Power management 639 */ 640 641 static int rcar_du_pm_suspend(struct device *dev) 642 { 643 struct rcar_du_device *rcdu = dev_get_drvdata(dev); 644 645 return drm_mode_config_helper_suspend(&rcdu->ddev); 646 } 647 648 static int rcar_du_pm_resume(struct device *dev) 649 { 650 struct rcar_du_device *rcdu = dev_get_drvdata(dev); 651 652 return drm_mode_config_helper_resume(&rcdu->ddev); 653 } 654 655 static DEFINE_SIMPLE_DEV_PM_OPS(rcar_du_pm_ops, 656 rcar_du_pm_suspend, rcar_du_pm_resume); 657 658 /* ----------------------------------------------------------------------------- 659 * Platform driver 660 */ 661 662 static void rcar_du_remove(struct platform_device *pdev) 663 { 664 struct rcar_du_device *rcdu = platform_get_drvdata(pdev); 665 struct drm_device *ddev = &rcdu->ddev; 666 667 drm_dev_unregister(ddev); 668 drm_atomic_helper_shutdown(ddev); 669 670 drm_kms_helper_poll_fini(ddev); 671 } 672 673 static void rcar_du_shutdown(struct platform_device *pdev) 674 { 675 struct rcar_du_device *rcdu = platform_get_drvdata(pdev); 676 677 drm_atomic_helper_shutdown(&rcdu->ddev); 678 } 679 680 static int rcar_du_probe(struct platform_device *pdev) 681 { 682 struct rcar_du_device *rcdu; 683 unsigned int mask; 684 int ret; 685 686 if (drm_firmware_drivers_only()) 687 return -ENODEV; 688 689 /* Allocate and initialize the R-Car device structure. */ 690 rcdu = devm_drm_dev_alloc(&pdev->dev, &rcar_du_driver, 691 struct rcar_du_device, ddev); 692 if (IS_ERR(rcdu)) 693 return PTR_ERR(rcdu); 694 695 rcdu->dev = &pdev->dev; 696 697 rcdu->info = of_device_get_match_data(rcdu->dev); 698 699 platform_set_drvdata(pdev, rcdu); 700 701 /* I/O resources */ 702 rcdu->mmio = devm_platform_ioremap_resource(pdev, 0); 703 if (IS_ERR(rcdu->mmio)) 704 return PTR_ERR(rcdu->mmio); 705 706 /* 707 * Set the DMA coherent mask to reflect the DU 32-bit DMA address space 708 * limitations. When sourcing frames from a VSP the DU doesn't perform 709 * any memory access so set the mask to 40 bits to accept all buffers. 710 */ 711 mask = rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE) ? 40 : 32; 712 ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(mask)); 713 if (ret) 714 return ret; 715 716 /* DRM/KMS objects */ 717 ret = rcar_du_modeset_init(rcdu); 718 if (ret < 0) { 719 /* 720 * Don't use dev_err_probe(), as it would overwrite the probe 721 * deferral reason recorded in rcar_du_modeset_init(). 722 */ 723 if (ret != -EPROBE_DEFER) 724 dev_err(&pdev->dev, 725 "failed to initialize DRM/KMS (%d)\n", ret); 726 goto error; 727 } 728 729 /* 730 * Register the DRM device with the core and the connectors with 731 * sysfs. 732 */ 733 ret = drm_dev_register(&rcdu->ddev, 0); 734 if (ret) 735 goto error; 736 737 drm_info(&rcdu->ddev, "Device %s probed\n", dev_name(&pdev->dev)); 738 739 drm_client_setup(&rcdu->ddev, NULL); 740 741 return 0; 742 743 error: 744 drm_kms_helper_poll_fini(&rcdu->ddev); 745 return ret; 746 } 747 748 static struct platform_driver rcar_du_platform_driver = { 749 .probe = rcar_du_probe, 750 .remove = rcar_du_remove, 751 .shutdown = rcar_du_shutdown, 752 .driver = { 753 .name = "rcar-du", 754 .pm = pm_sleep_ptr(&rcar_du_pm_ops), 755 .of_match_table = rcar_du_of_table, 756 }, 757 }; 758 759 module_platform_driver(rcar_du_platform_driver); 760 761 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 762 MODULE_DESCRIPTION("Renesas R-Car Display Unit DRM Driver"); 763 MODULE_LICENSE("GPL"); 764