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