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