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