Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.2 724 lines 18 kB view raw
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 35static 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 59static 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 82static 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 110static 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 141static 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 172static 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 200static 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 231static 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 252static 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 */ 284static 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 309static 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 330static 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 354static 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 389static 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 420static 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 451static 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 477static 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 506static const struct rcar_du_device_info rcar_du_r8a779a0_info = { 507 .gen = 3, 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 527static const struct of_device_id rcar_du_of_table[] = { 528 { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info }, 529 { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info }, 530 { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info }, 531 { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info }, 532 { .compatible = "renesas,du-r8a77470", .data = &rzg1_du_r8a77470_info }, 533 { .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info }, 534 { .compatible = "renesas,du-r8a774b1", .data = &rcar_du_r8a774b1_info }, 535 { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info }, 536 { .compatible = "renesas,du-r8a774e1", .data = &rcar_du_r8a774e1_info }, 537 { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info }, 538 { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info }, 539 { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info }, 540 { .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info }, 541 { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info }, 542 { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info }, 543 { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, 544 { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, 545 { .compatible = "renesas,du-r8a77961", .data = &rcar_du_r8a7796_info }, 546 { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, 547 { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info }, 548 { .compatible = "renesas,du-r8a77980", .data = &rcar_du_r8a77970_info }, 549 { .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info }, 550 { .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info }, 551 { .compatible = "renesas,du-r8a779a0", .data = &rcar_du_r8a779a0_info }, 552 { } 553}; 554 555MODULE_DEVICE_TABLE(of, rcar_du_of_table); 556 557const char *rcar_du_output_name(enum rcar_du_output output) 558{ 559 static const char * const names[] = { 560 [RCAR_DU_OUTPUT_DPAD0] = "DPAD0", 561 [RCAR_DU_OUTPUT_DPAD1] = "DPAD1", 562 [RCAR_DU_OUTPUT_DSI0] = "DSI0", 563 [RCAR_DU_OUTPUT_DSI1] = "DSI1", 564 [RCAR_DU_OUTPUT_HDMI0] = "HDMI0", 565 [RCAR_DU_OUTPUT_HDMI1] = "HDMI1", 566 [RCAR_DU_OUTPUT_LVDS0] = "LVDS0", 567 [RCAR_DU_OUTPUT_LVDS1] = "LVDS1", 568 [RCAR_DU_OUTPUT_TCON] = "TCON", 569 }; 570 571 if (output >= ARRAY_SIZE(names) || !names[output]) 572 return "UNKNOWN"; 573 574 return names[output]; 575} 576 577/* ----------------------------------------------------------------------------- 578 * DRM operations 579 */ 580 581DEFINE_DRM_GEM_DMA_FOPS(rcar_du_fops); 582 583static const struct drm_driver rcar_du_driver = { 584 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, 585 .dumb_create = rcar_du_dumb_create, 586 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 587 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 588 .gem_prime_import_sg_table = rcar_du_gem_prime_import_sg_table, 589 .gem_prime_mmap = drm_gem_prime_mmap, 590 .fops = &rcar_du_fops, 591 .name = "rcar-du", 592 .desc = "Renesas R-Car Display Unit", 593 .date = "20130110", 594 .major = 1, 595 .minor = 0, 596}; 597 598/* ----------------------------------------------------------------------------- 599 * Power management 600 */ 601 602#ifdef CONFIG_PM_SLEEP 603static int rcar_du_pm_suspend(struct device *dev) 604{ 605 struct rcar_du_device *rcdu = dev_get_drvdata(dev); 606 607 return drm_mode_config_helper_suspend(&rcdu->ddev); 608} 609 610static int rcar_du_pm_resume(struct device *dev) 611{ 612 struct rcar_du_device *rcdu = dev_get_drvdata(dev); 613 614 return drm_mode_config_helper_resume(&rcdu->ddev); 615} 616#endif 617 618static const struct dev_pm_ops rcar_du_pm_ops = { 619 SET_SYSTEM_SLEEP_PM_OPS(rcar_du_pm_suspend, rcar_du_pm_resume) 620}; 621 622/* ----------------------------------------------------------------------------- 623 * Platform driver 624 */ 625 626static int rcar_du_remove(struct platform_device *pdev) 627{ 628 struct rcar_du_device *rcdu = platform_get_drvdata(pdev); 629 struct drm_device *ddev = &rcdu->ddev; 630 631 drm_dev_unregister(ddev); 632 drm_atomic_helper_shutdown(ddev); 633 634 drm_kms_helper_poll_fini(ddev); 635 636 return 0; 637} 638 639static void rcar_du_shutdown(struct platform_device *pdev) 640{ 641 struct rcar_du_device *rcdu = platform_get_drvdata(pdev); 642 643 drm_atomic_helper_shutdown(&rcdu->ddev); 644} 645 646static int rcar_du_probe(struct platform_device *pdev) 647{ 648 struct rcar_du_device *rcdu; 649 unsigned int mask; 650 int ret; 651 652 if (drm_firmware_drivers_only()) 653 return -ENODEV; 654 655 /* Allocate and initialize the R-Car device structure. */ 656 rcdu = devm_drm_dev_alloc(&pdev->dev, &rcar_du_driver, 657 struct rcar_du_device, ddev); 658 if (IS_ERR(rcdu)) 659 return PTR_ERR(rcdu); 660 661 rcdu->dev = &pdev->dev; 662 rcdu->info = of_device_get_match_data(rcdu->dev); 663 664 platform_set_drvdata(pdev, rcdu); 665 666 /* I/O resources */ 667 rcdu->mmio = devm_platform_ioremap_resource(pdev, 0); 668 if (IS_ERR(rcdu->mmio)) 669 return PTR_ERR(rcdu->mmio); 670 671 /* 672 * Set the DMA coherent mask to reflect the DU 32-bit DMA address space 673 * limitations. When sourcing frames from a VSP the DU doesn't perform 674 * any memory access so set the mask to 40 bits to accept all buffers. 675 */ 676 mask = rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE) ? 40 : 32; 677 ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(mask)); 678 if (ret) 679 return ret; 680 681 /* DRM/KMS objects */ 682 ret = rcar_du_modeset_init(rcdu); 683 if (ret < 0) { 684 if (ret != -EPROBE_DEFER) 685 dev_err(&pdev->dev, 686 "failed to initialize DRM/KMS (%d)\n", ret); 687 goto error; 688 } 689 690 /* 691 * Register the DRM device with the core and the connectors with 692 * sysfs. 693 */ 694 ret = drm_dev_register(&rcdu->ddev, 0); 695 if (ret) 696 goto error; 697 698 DRM_INFO("Device %s probed\n", dev_name(&pdev->dev)); 699 700 drm_fbdev_generic_setup(&rcdu->ddev, 32); 701 702 return 0; 703 704error: 705 drm_kms_helper_poll_fini(&rcdu->ddev); 706 return ret; 707} 708 709static struct platform_driver rcar_du_platform_driver = { 710 .probe = rcar_du_probe, 711 .remove = rcar_du_remove, 712 .shutdown = rcar_du_shutdown, 713 .driver = { 714 .name = "rcar-du", 715 .pm = &rcar_du_pm_ops, 716 .of_match_table = rcar_du_of_table, 717 }, 718}; 719 720module_platform_driver(rcar_du_platform_driver); 721 722MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 723MODULE_DESCRIPTION("Renesas R-Car Display Unit DRM Driver"); 724MODULE_LICENSE("GPL");