linux/drivers/gpu/drm/rcar-du/rcar_du_drv.c
<<
>>
Prefs
   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/io.h>
  12#include <linux/mm.h>
  13#include <linux/module.h>
  14#include <linux/of_device.h>
  15#include <linux/platform_device.h>
  16#include <linux/pm.h>
  17#include <linux/slab.h>
  18#include <linux/wait.h>
  19
  20#include <drm/drm_atomic_helper.h>
  21#include <drm/drm_fb_cma_helper.h>
  22#include <drm/drm_fb_helper.h>
  23#include <drm/drm_drv.h>
  24#include <drm/drm_gem_cma_helper.h>
  25#include <drm/drm_probe_helper.h>
  26
  27#include "rcar_du_drv.h"
  28#include "rcar_du_kms.h"
  29#include "rcar_du_of.h"
  30#include "rcar_du_regs.h"
  31
  32/* -----------------------------------------------------------------------------
  33 * Device Information
  34 */
  35
  36static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
  37        .gen = 2,
  38        .features = RCAR_DU_FEATURE_CRTC_IRQ_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};
  57
  58static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
  59        .gen = 2,
  60        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
  61                  | RCAR_DU_FEATURE_INTERLACED
  62                  | RCAR_DU_FEATURE_TVM_SYNC,
  63        .channels_mask = BIT(1) | BIT(0),
  64        .routes = {
  65                /*
  66                 * R8A7745 has two RGB outputs
  67                 */
  68                [RCAR_DU_OUTPUT_DPAD0] = {
  69                        .possible_crtcs = BIT(0),
  70                        .port = 0,
  71                },
  72                [RCAR_DU_OUTPUT_DPAD1] = {
  73                        .possible_crtcs = BIT(1),
  74                        .port = 1,
  75                },
  76        },
  77};
  78
  79static const struct rcar_du_device_info rzg1_du_r8a77470_info = {
  80        .gen = 2,
  81        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
  82                  | RCAR_DU_FEATURE_INTERLACED
  83                  | RCAR_DU_FEATURE_TVM_SYNC,
  84        .channels_mask = BIT(1) | BIT(0),
  85        .routes = {
  86                /*
  87                 * R8A77470 has two RGB outputs, one LVDS output, and
  88                 * one (currently unsupported) analog video output
  89                 */
  90                [RCAR_DU_OUTPUT_DPAD0] = {
  91                        .possible_crtcs = BIT(0),
  92                        .port = 0,
  93                },
  94                [RCAR_DU_OUTPUT_DPAD1] = {
  95                        .possible_crtcs = BIT(1),
  96                        .port = 1,
  97                },
  98                [RCAR_DU_OUTPUT_LVDS0] = {
  99                        .possible_crtcs = BIT(0) | BIT(1),
 100                        .port = 2,
 101                },
 102        },
 103};
 104
 105static const struct rcar_du_device_info rcar_du_r8a774a1_info = {
 106        .gen = 3,
 107        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 108                  | RCAR_DU_FEATURE_VSP1_SOURCE
 109                  | RCAR_DU_FEATURE_INTERLACED
 110                  | RCAR_DU_FEATURE_TVM_SYNC,
 111        .channels_mask = BIT(2) | BIT(1) | BIT(0),
 112        .routes = {
 113                /*
 114                 * R8A774A1 has one RGB output, one LVDS output and one HDMI
 115                 * output.
 116                 */
 117                [RCAR_DU_OUTPUT_DPAD0] = {
 118                        .possible_crtcs = BIT(2),
 119                        .port = 0,
 120                },
 121                [RCAR_DU_OUTPUT_HDMI0] = {
 122                        .possible_crtcs = BIT(1),
 123                        .port = 1,
 124                },
 125                [RCAR_DU_OUTPUT_LVDS0] = {
 126                        .possible_crtcs = BIT(0),
 127                        .port = 2,
 128                },
 129        },
 130        .num_lvds = 1,
 131        .dpll_mask =  BIT(1),
 132};
 133
 134static const struct rcar_du_device_info rcar_du_r8a774b1_info = {
 135        .gen = 3,
 136        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 137                  | RCAR_DU_FEATURE_VSP1_SOURCE
 138                  | RCAR_DU_FEATURE_INTERLACED
 139                  | RCAR_DU_FEATURE_TVM_SYNC,
 140        .channels_mask = BIT(3) | BIT(1) | BIT(0),
 141        .routes = {
 142                /*
 143                 * R8A774B1 has one RGB output, one LVDS output and one HDMI
 144                 * output.
 145                 */
 146                [RCAR_DU_OUTPUT_DPAD0] = {
 147                        .possible_crtcs = BIT(2),
 148                        .port = 0,
 149                },
 150                [RCAR_DU_OUTPUT_HDMI0] = {
 151                        .possible_crtcs = BIT(1),
 152                        .port = 1,
 153                },
 154                [RCAR_DU_OUTPUT_LVDS0] = {
 155                        .possible_crtcs = BIT(0),
 156                        .port = 2,
 157                },
 158        },
 159        .num_lvds = 1,
 160        .dpll_mask =  BIT(1),
 161};
 162
 163static const struct rcar_du_device_info rcar_du_r8a774c0_info = {
 164        .gen = 3,
 165        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 166                  | RCAR_DU_FEATURE_VSP1_SOURCE,
 167        .channels_mask = BIT(1) | BIT(0),
 168        .routes = {
 169                /*
 170                 * R8A774C0 has one RGB output and two LVDS outputs
 171                 */
 172                [RCAR_DU_OUTPUT_DPAD0] = {
 173                        .possible_crtcs = BIT(0) | BIT(1),
 174                        .port = 0,
 175                },
 176                [RCAR_DU_OUTPUT_LVDS0] = {
 177                        .possible_crtcs = BIT(0),
 178                        .port = 1,
 179                },
 180                [RCAR_DU_OUTPUT_LVDS1] = {
 181                        .possible_crtcs = BIT(1),
 182                        .port = 2,
 183                },
 184        },
 185        .num_lvds = 2,
 186        .lvds_clk_mask =  BIT(1) | BIT(0),
 187};
 188
 189static const struct rcar_du_device_info rcar_du_r8a774e1_info = {
 190        .gen = 3,
 191        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 192                  | RCAR_DU_FEATURE_VSP1_SOURCE
 193                  | RCAR_DU_FEATURE_INTERLACED
 194                  | RCAR_DU_FEATURE_TVM_SYNC,
 195        .channels_mask = BIT(3) | BIT(1) | BIT(0),
 196        .routes = {
 197                /*
 198                 * R8A774E1 has one RGB output, one LVDS output and one HDMI
 199                 * output.
 200                 */
 201                [RCAR_DU_OUTPUT_DPAD0] = {
 202                        .possible_crtcs = BIT(2),
 203                        .port = 0,
 204                },
 205                [RCAR_DU_OUTPUT_HDMI0] = {
 206                        .possible_crtcs = BIT(1),
 207                        .port = 1,
 208                },
 209                [RCAR_DU_OUTPUT_LVDS0] = {
 210                        .possible_crtcs = BIT(0),
 211                        .port = 2,
 212                },
 213        },
 214        .num_lvds = 1,
 215        .dpll_mask =  BIT(1),
 216};
 217
 218static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 219        .gen = 1,
 220        .features = RCAR_DU_FEATURE_INTERLACED
 221                  | RCAR_DU_FEATURE_TVM_SYNC,
 222        .channels_mask = BIT(1) | BIT(0),
 223        .routes = {
 224                /*
 225                 * R8A7779 has two RGB outputs and one (currently unsupported)
 226                 * TCON output.
 227                 */
 228                [RCAR_DU_OUTPUT_DPAD0] = {
 229                        .possible_crtcs = BIT(0),
 230                        .port = 0,
 231                },
 232                [RCAR_DU_OUTPUT_DPAD1] = {
 233                        .possible_crtcs = BIT(1) | BIT(0),
 234                        .port = 1,
 235                },
 236        },
 237};
 238
 239static const struct rcar_du_device_info rcar_du_r8a7790_info = {
 240        .gen = 2,
 241        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 242                  | RCAR_DU_FEATURE_INTERLACED
 243                  | RCAR_DU_FEATURE_TVM_SYNC,
 244        .quirks = RCAR_DU_QUIRK_ALIGN_128B,
 245        .channels_mask = BIT(2) | BIT(1) | BIT(0),
 246        .routes = {
 247                /*
 248                 * R8A7742 and R8A7790 each have one RGB output and two LVDS
 249                 * outputs. Additionally R8A7790 supports one TCON output
 250                 * (currently unsupported by the driver).
 251                 */
 252                [RCAR_DU_OUTPUT_DPAD0] = {
 253                        .possible_crtcs = BIT(2) | BIT(1) | BIT(0),
 254                        .port = 0,
 255                },
 256                [RCAR_DU_OUTPUT_LVDS0] = {
 257                        .possible_crtcs = BIT(0),
 258                        .port = 1,
 259                },
 260                [RCAR_DU_OUTPUT_LVDS1] = {
 261                        .possible_crtcs = BIT(2) | BIT(1),
 262                        .port = 2,
 263                },
 264        },
 265        .num_lvds = 2,
 266};
 267
 268/* M2-W (r8a7791) and M2-N (r8a7793) are identical */
 269static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 270        .gen = 2,
 271        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 272                  | RCAR_DU_FEATURE_INTERLACED
 273                  | RCAR_DU_FEATURE_TVM_SYNC,
 274        .channels_mask = BIT(1) | BIT(0),
 275        .routes = {
 276                /*
 277                 * R8A779[13] has one RGB output, one LVDS output and one
 278                 * (currently unsupported) TCON output.
 279                 */
 280                [RCAR_DU_OUTPUT_DPAD0] = {
 281                        .possible_crtcs = BIT(1) | BIT(0),
 282                        .port = 0,
 283                },
 284                [RCAR_DU_OUTPUT_LVDS0] = {
 285                        .possible_crtcs = BIT(0),
 286                        .port = 1,
 287                },
 288        },
 289        .num_lvds = 1,
 290};
 291
 292static const struct rcar_du_device_info rcar_du_r8a7792_info = {
 293        .gen = 2,
 294        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 295                  | RCAR_DU_FEATURE_INTERLACED
 296                  | RCAR_DU_FEATURE_TVM_SYNC,
 297        .channels_mask = BIT(1) | BIT(0),
 298        .routes = {
 299                /* R8A7792 has two RGB outputs. */
 300                [RCAR_DU_OUTPUT_DPAD0] = {
 301                        .possible_crtcs = BIT(0),
 302                        .port = 0,
 303                },
 304                [RCAR_DU_OUTPUT_DPAD1] = {
 305                        .possible_crtcs = BIT(1),
 306                        .port = 1,
 307                },
 308        },
 309};
 310
 311static const struct rcar_du_device_info rcar_du_r8a7794_info = {
 312        .gen = 2,
 313        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 314                  | RCAR_DU_FEATURE_INTERLACED
 315                  | RCAR_DU_FEATURE_TVM_SYNC,
 316        .channels_mask = BIT(1) | BIT(0),
 317        .routes = {
 318                /*
 319                 * R8A7794 has two RGB outputs and one (currently unsupported)
 320                 * TCON output.
 321                 */
 322                [RCAR_DU_OUTPUT_DPAD0] = {
 323                        .possible_crtcs = BIT(0),
 324                        .port = 0,
 325                },
 326                [RCAR_DU_OUTPUT_DPAD1] = {
 327                        .possible_crtcs = BIT(1),
 328                        .port = 1,
 329                },
 330        },
 331};
 332
 333static const struct rcar_du_device_info rcar_du_r8a7795_info = {
 334        .gen = 3,
 335        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 336                  | RCAR_DU_FEATURE_VSP1_SOURCE
 337                  | RCAR_DU_FEATURE_INTERLACED
 338                  | RCAR_DU_FEATURE_TVM_SYNC,
 339        .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
 340        .routes = {
 341                /*
 342                 * R8A7795 has one RGB output, two HDMI outputs and one
 343                 * LVDS output.
 344                 */
 345                [RCAR_DU_OUTPUT_DPAD0] = {
 346                        .possible_crtcs = BIT(3),
 347                        .port = 0,
 348                },
 349                [RCAR_DU_OUTPUT_HDMI0] = {
 350                        .possible_crtcs = BIT(1),
 351                        .port = 1,
 352                },
 353                [RCAR_DU_OUTPUT_HDMI1] = {
 354                        .possible_crtcs = BIT(2),
 355                        .port = 2,
 356                },
 357                [RCAR_DU_OUTPUT_LVDS0] = {
 358                        .possible_crtcs = BIT(0),
 359                        .port = 3,
 360                },
 361        },
 362        .num_lvds = 1,
 363        .dpll_mask =  BIT(2) | BIT(1),
 364};
 365
 366static const struct rcar_du_device_info rcar_du_r8a7796_info = {
 367        .gen = 3,
 368        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 369                  | RCAR_DU_FEATURE_VSP1_SOURCE
 370                  | RCAR_DU_FEATURE_INTERLACED
 371                  | RCAR_DU_FEATURE_TVM_SYNC,
 372        .channels_mask = BIT(2) | BIT(1) | BIT(0),
 373        .routes = {
 374                /*
 375                 * R8A7796 has one RGB output, one LVDS output and one HDMI
 376                 * output.
 377                 */
 378                [RCAR_DU_OUTPUT_DPAD0] = {
 379                        .possible_crtcs = BIT(2),
 380                        .port = 0,
 381                },
 382                [RCAR_DU_OUTPUT_HDMI0] = {
 383                        .possible_crtcs = BIT(1),
 384                        .port = 1,
 385                },
 386                [RCAR_DU_OUTPUT_LVDS0] = {
 387                        .possible_crtcs = BIT(0),
 388                        .port = 2,
 389                },
 390        },
 391        .num_lvds = 1,
 392        .dpll_mask =  BIT(1),
 393};
 394
 395static const struct rcar_du_device_info rcar_du_r8a77965_info = {
 396        .gen = 3,
 397        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 398                  | RCAR_DU_FEATURE_VSP1_SOURCE
 399                  | RCAR_DU_FEATURE_INTERLACED
 400                  | RCAR_DU_FEATURE_TVM_SYNC,
 401        .channels_mask = BIT(3) | BIT(1) | BIT(0),
 402        .routes = {
 403                /*
 404                 * R8A77965 has one RGB output, one LVDS output and one HDMI
 405                 * output.
 406                 */
 407                [RCAR_DU_OUTPUT_DPAD0] = {
 408                        .possible_crtcs = BIT(2),
 409                        .port = 0,
 410                },
 411                [RCAR_DU_OUTPUT_HDMI0] = {
 412                        .possible_crtcs = BIT(1),
 413                        .port = 1,
 414                },
 415                [RCAR_DU_OUTPUT_LVDS0] = {
 416                        .possible_crtcs = BIT(0),
 417                        .port = 2,
 418                },
 419        },
 420        .num_lvds = 1,
 421        .dpll_mask =  BIT(1),
 422};
 423
 424static const struct rcar_du_device_info rcar_du_r8a77970_info = {
 425        .gen = 3,
 426        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 427                  | RCAR_DU_FEATURE_VSP1_SOURCE
 428                  | RCAR_DU_FEATURE_INTERLACED
 429                  | RCAR_DU_FEATURE_TVM_SYNC,
 430        .channels_mask = BIT(0),
 431        .routes = {
 432                /*
 433                 * R8A77970 and R8A77980 have one RGB output and one LVDS
 434                 * output.
 435                 */
 436                [RCAR_DU_OUTPUT_DPAD0] = {
 437                        .possible_crtcs = BIT(0),
 438                        .port = 0,
 439                },
 440                [RCAR_DU_OUTPUT_LVDS0] = {
 441                        .possible_crtcs = BIT(0),
 442                        .port = 1,
 443                },
 444        },
 445        .num_lvds = 1,
 446};
 447
 448static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
 449        .gen = 3,
 450        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 451                  | RCAR_DU_FEATURE_VSP1_SOURCE,
 452        .channels_mask = BIT(1) | BIT(0),
 453        .routes = {
 454                /*
 455                 * R8A77990 and R8A77995 have one RGB output and two LVDS
 456                 * outputs.
 457                 */
 458                [RCAR_DU_OUTPUT_DPAD0] = {
 459                        .possible_crtcs = BIT(0) | BIT(1),
 460                        .port = 0,
 461                },
 462                [RCAR_DU_OUTPUT_LVDS0] = {
 463                        .possible_crtcs = BIT(0),
 464                        .port = 1,
 465                },
 466                [RCAR_DU_OUTPUT_LVDS1] = {
 467                        .possible_crtcs = BIT(1),
 468                        .port = 2,
 469                },
 470        },
 471        .num_lvds = 2,
 472        .lvds_clk_mask =  BIT(1) | BIT(0),
 473};
 474
 475static const struct of_device_id rcar_du_of_table[] = {
 476        { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info },
 477        { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info },
 478        { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info },
 479        { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info },
 480        { .compatible = "renesas,du-r8a77470", .data = &rzg1_du_r8a77470_info },
 481        { .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info },
 482        { .compatible = "renesas,du-r8a774b1", .data = &rcar_du_r8a774b1_info },
 483        { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info },
 484        { .compatible = "renesas,du-r8a774e1", .data = &rcar_du_r8a774e1_info },
 485        { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
 486        { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
 487        { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
 488        { .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info },
 489        { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
 490        { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
 491        { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
 492        { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
 493        { .compatible = "renesas,du-r8a77961", .data = &rcar_du_r8a7796_info },
 494        { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info },
 495        { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info },
 496        { .compatible = "renesas,du-r8a77980", .data = &rcar_du_r8a77970_info },
 497        { .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info },
 498        { .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info },
 499        { }
 500};
 501
 502MODULE_DEVICE_TABLE(of, rcar_du_of_table);
 503
 504/* -----------------------------------------------------------------------------
 505 * DRM operations
 506 */
 507
 508DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
 509
 510static struct drm_driver rcar_du_driver = {
 511        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 512        DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(rcar_du_dumb_create),
 513        .fops                   = &rcar_du_fops,
 514        .name                   = "rcar-du",
 515        .desc                   = "Renesas R-Car Display Unit",
 516        .date                   = "20130110",
 517        .major                  = 1,
 518        .minor                  = 0,
 519};
 520
 521/* -----------------------------------------------------------------------------
 522 * Power management
 523 */
 524
 525#ifdef CONFIG_PM_SLEEP
 526static int rcar_du_pm_suspend(struct device *dev)
 527{
 528        struct rcar_du_device *rcdu = dev_get_drvdata(dev);
 529
 530        return drm_mode_config_helper_suspend(rcdu->ddev);
 531}
 532
 533static int rcar_du_pm_resume(struct device *dev)
 534{
 535        struct rcar_du_device *rcdu = dev_get_drvdata(dev);
 536
 537        return drm_mode_config_helper_resume(rcdu->ddev);
 538}
 539#endif
 540
 541static const struct dev_pm_ops rcar_du_pm_ops = {
 542        SET_SYSTEM_SLEEP_PM_OPS(rcar_du_pm_suspend, rcar_du_pm_resume)
 543};
 544
 545/* -----------------------------------------------------------------------------
 546 * Platform driver
 547 */
 548
 549static int rcar_du_remove(struct platform_device *pdev)
 550{
 551        struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
 552        struct drm_device *ddev = rcdu->ddev;
 553
 554        drm_dev_unregister(ddev);
 555
 556        drm_kms_helper_poll_fini(ddev);
 557
 558        drm_dev_put(ddev);
 559
 560        return 0;
 561}
 562
 563static int rcar_du_probe(struct platform_device *pdev)
 564{
 565        struct rcar_du_device *rcdu;
 566        struct drm_device *ddev;
 567        struct resource *mem;
 568        int ret;
 569
 570        /* Allocate and initialize the R-Car device structure. */
 571        rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
 572        if (rcdu == NULL)
 573                return -ENOMEM;
 574
 575        rcdu->dev = &pdev->dev;
 576        rcdu->info = of_device_get_match_data(rcdu->dev);
 577
 578        platform_set_drvdata(pdev, rcdu);
 579
 580        /* I/O resources */
 581        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 582        rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
 583        if (IS_ERR(rcdu->mmio))
 584                return PTR_ERR(rcdu->mmio);
 585
 586        /* DRM/KMS objects */
 587        ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
 588        if (IS_ERR(ddev))
 589                return PTR_ERR(ddev);
 590
 591        rcdu->ddev = ddev;
 592        ddev->dev_private = rcdu;
 593
 594        ret = rcar_du_modeset_init(rcdu);
 595        if (ret < 0) {
 596                if (ret != -EPROBE_DEFER)
 597                        dev_err(&pdev->dev,
 598                                "failed to initialize DRM/KMS (%d)\n", ret);
 599                goto error;
 600        }
 601
 602        ddev->irq_enabled = 1;
 603
 604        /*
 605         * Register the DRM device with the core and the connectors with
 606         * sysfs.
 607         */
 608        ret = drm_dev_register(ddev, 0);
 609        if (ret)
 610                goto error;
 611
 612        DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
 613
 614        drm_fbdev_generic_setup(ddev, 32);
 615
 616        return 0;
 617
 618error:
 619        rcar_du_remove(pdev);
 620
 621        return ret;
 622}
 623
 624static struct platform_driver rcar_du_platform_driver = {
 625        .probe          = rcar_du_probe,
 626        .remove         = rcar_du_remove,
 627        .driver         = {
 628                .name   = "rcar-du",
 629                .pm     = &rcar_du_pm_ops,
 630                .of_match_table = rcar_du_of_table,
 631        },
 632};
 633
 634static int __init rcar_du_init(void)
 635{
 636        rcar_du_of_init(rcar_du_of_table);
 637
 638        return platform_driver_register(&rcar_du_platform_driver);
 639}
 640module_init(rcar_du_init);
 641
 642static void __exit rcar_du_exit(void)
 643{
 644        platform_driver_unregister(&rcar_du_platform_driver);
 645}
 646module_exit(rcar_du_exit);
 647
 648MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
 649MODULE_DESCRIPTION("Renesas R-Car Display Unit DRM Driver");
 650MODULE_LICENSE("GPL");
 651