Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * R-Car Display Unit DRM driver
0004  *
0005  * Copyright (C) 2013-2015 Renesas Electronics Corporation
0006  *
0007  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
0008  */
0009 
0010 #include <linux/clk.h>
0011 #include <linux/dma-mapping.h>
0012 #include <linux/io.h>
0013 #include <linux/mm.h>
0014 #include <linux/module.h>
0015 #include <linux/of_device.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/pm.h>
0018 #include <linux/slab.h>
0019 #include <linux/wait.h>
0020 
0021 #include <drm/drm_atomic_helper.h>
0022 #include <drm/drm_drv.h>
0023 #include <drm/drm_fb_cma_helper.h>
0024 #include <drm/drm_fb_helper.h>
0025 #include <drm/drm_gem_cma_helper.h>
0026 #include <drm/drm_managed.h>
0027 #include <drm/drm_probe_helper.h>
0028 
0029 #include "rcar_du_drv.h"
0030 #include "rcar_du_kms.h"
0031 #include "rcar_du_regs.h"
0032 
0033 /* -----------------------------------------------------------------------------
0034  * Device Information
0035  */
0036 
0037 static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
0038     .gen = 2,
0039     .features = RCAR_DU_FEATURE_CRTC_IRQ
0040           | RCAR_DU_FEATURE_CRTC_CLOCK
0041           | RCAR_DU_FEATURE_INTERLACED
0042           | RCAR_DU_FEATURE_TVM_SYNC,
0043     .channels_mask = BIT(1) | BIT(0),
0044     .routes = {
0045         /*
0046          * R8A774[34] has one RGB output and one LVDS output
0047          */
0048         [RCAR_DU_OUTPUT_DPAD0] = {
0049             .possible_crtcs = BIT(1) | BIT(0),
0050             .port = 0,
0051         },
0052         [RCAR_DU_OUTPUT_LVDS0] = {
0053             .possible_crtcs = BIT(0),
0054             .port = 1,
0055         },
0056     },
0057     .num_lvds = 1,
0058     .num_rpf = 4,
0059 };
0060 
0061 static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
0062     .gen = 2,
0063     .features = RCAR_DU_FEATURE_CRTC_IRQ
0064           | RCAR_DU_FEATURE_CRTC_CLOCK
0065           | RCAR_DU_FEATURE_INTERLACED
0066           | RCAR_DU_FEATURE_TVM_SYNC,
0067     .channels_mask = BIT(1) | BIT(0),
0068     .routes = {
0069         /*
0070          * R8A7745 has two RGB outputs
0071          */
0072         [RCAR_DU_OUTPUT_DPAD0] = {
0073             .possible_crtcs = BIT(0),
0074             .port = 0,
0075         },
0076         [RCAR_DU_OUTPUT_DPAD1] = {
0077             .possible_crtcs = BIT(1),
0078             .port = 1,
0079         },
0080     },
0081     .num_rpf = 4,
0082 };
0083 
0084 static const struct rcar_du_device_info rzg1_du_r8a77470_info = {
0085     .gen = 2,
0086     .features = RCAR_DU_FEATURE_CRTC_IRQ
0087           | RCAR_DU_FEATURE_CRTC_CLOCK
0088           | RCAR_DU_FEATURE_INTERLACED
0089           | RCAR_DU_FEATURE_TVM_SYNC,
0090     .channels_mask = BIT(1) | BIT(0),
0091     .routes = {
0092         /*
0093          * R8A77470 has two RGB outputs, one LVDS output, and
0094          * one (currently unsupported) analog video output
0095          */
0096         [RCAR_DU_OUTPUT_DPAD0] = {
0097             .possible_crtcs = BIT(0),
0098             .port = 0,
0099         },
0100         [RCAR_DU_OUTPUT_DPAD1] = {
0101             .possible_crtcs = BIT(1),
0102             .port = 1,
0103         },
0104         [RCAR_DU_OUTPUT_LVDS0] = {
0105             .possible_crtcs = BIT(0) | BIT(1),
0106             .port = 2,
0107         },
0108     },
0109     .num_rpf = 4,
0110 };
0111 
0112 static const struct rcar_du_device_info rcar_du_r8a774a1_info = {
0113     .gen = 3,
0114     .features = RCAR_DU_FEATURE_CRTC_IRQ
0115           | RCAR_DU_FEATURE_CRTC_CLOCK
0116           | RCAR_DU_FEATURE_VSP1_SOURCE
0117           | RCAR_DU_FEATURE_INTERLACED
0118           | RCAR_DU_FEATURE_TVM_SYNC,
0119     .channels_mask = BIT(2) | BIT(1) | BIT(0),
0120     .routes = {
0121         /*
0122          * R8A774A1 has one RGB output, one LVDS output and one HDMI
0123          * output.
0124          */
0125         [RCAR_DU_OUTPUT_DPAD0] = {
0126             .possible_crtcs = BIT(2),
0127             .port = 0,
0128         },
0129         [RCAR_DU_OUTPUT_HDMI0] = {
0130             .possible_crtcs = BIT(1),
0131             .port = 1,
0132         },
0133         [RCAR_DU_OUTPUT_LVDS0] = {
0134             .possible_crtcs = BIT(0),
0135             .port = 2,
0136         },
0137     },
0138     .num_lvds = 1,
0139     .num_rpf = 5,
0140     .dpll_mask =  BIT(1),
0141 };
0142 
0143 static const struct rcar_du_device_info rcar_du_r8a774b1_info = {
0144     .gen = 3,
0145     .features = RCAR_DU_FEATURE_CRTC_IRQ
0146           | RCAR_DU_FEATURE_CRTC_CLOCK
0147           | RCAR_DU_FEATURE_VSP1_SOURCE
0148           | RCAR_DU_FEATURE_INTERLACED
0149           | RCAR_DU_FEATURE_TVM_SYNC,
0150     .channels_mask = BIT(3) | BIT(1) | BIT(0),
0151     .routes = {
0152         /*
0153          * R8A774B1 has one RGB output, one LVDS output and one HDMI
0154          * output.
0155          */
0156         [RCAR_DU_OUTPUT_DPAD0] = {
0157             .possible_crtcs = BIT(2),
0158             .port = 0,
0159         },
0160         [RCAR_DU_OUTPUT_HDMI0] = {
0161             .possible_crtcs = BIT(1),
0162             .port = 1,
0163         },
0164         [RCAR_DU_OUTPUT_LVDS0] = {
0165             .possible_crtcs = BIT(0),
0166             .port = 2,
0167         },
0168     },
0169     .num_lvds = 1,
0170     .num_rpf = 5,
0171     .dpll_mask =  BIT(1),
0172 };
0173 
0174 static const struct rcar_du_device_info rcar_du_r8a774c0_info = {
0175     .gen = 3,
0176     .features = RCAR_DU_FEATURE_CRTC_IRQ
0177           | RCAR_DU_FEATURE_CRTC_CLOCK
0178           | RCAR_DU_FEATURE_VSP1_SOURCE,
0179     .channels_mask = BIT(1) | BIT(0),
0180     .routes = {
0181         /*
0182          * R8A774C0 has one RGB output and two LVDS outputs
0183          */
0184         [RCAR_DU_OUTPUT_DPAD0] = {
0185             .possible_crtcs = BIT(0) | BIT(1),
0186             .port = 0,
0187         },
0188         [RCAR_DU_OUTPUT_LVDS0] = {
0189             .possible_crtcs = BIT(0),
0190             .port = 1,
0191         },
0192         [RCAR_DU_OUTPUT_LVDS1] = {
0193             .possible_crtcs = BIT(1),
0194             .port = 2,
0195         },
0196     },
0197     .num_lvds = 2,
0198     .num_rpf = 4,
0199     .lvds_clk_mask =  BIT(1) | BIT(0),
0200 };
0201 
0202 static const struct rcar_du_device_info rcar_du_r8a774e1_info = {
0203     .gen = 3,
0204     .features = RCAR_DU_FEATURE_CRTC_IRQ
0205           | RCAR_DU_FEATURE_CRTC_CLOCK
0206           | RCAR_DU_FEATURE_VSP1_SOURCE
0207           | RCAR_DU_FEATURE_INTERLACED
0208           | RCAR_DU_FEATURE_TVM_SYNC,
0209     .channels_mask = BIT(3) | BIT(1) | BIT(0),
0210     .routes = {
0211         /*
0212          * R8A774E1 has one RGB output, one LVDS output and one HDMI
0213          * output.
0214          */
0215         [RCAR_DU_OUTPUT_DPAD0] = {
0216             .possible_crtcs = BIT(2),
0217             .port = 0,
0218         },
0219         [RCAR_DU_OUTPUT_HDMI0] = {
0220             .possible_crtcs = BIT(1),
0221             .port = 1,
0222         },
0223         [RCAR_DU_OUTPUT_LVDS0] = {
0224             .possible_crtcs = BIT(0),
0225             .port = 2,
0226         },
0227     },
0228     .num_lvds = 1,
0229     .num_rpf = 5,
0230     .dpll_mask =  BIT(1),
0231 };
0232 
0233 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
0234     .gen = 1,
0235     .features = RCAR_DU_FEATURE_INTERLACED
0236           | RCAR_DU_FEATURE_TVM_SYNC,
0237     .channels_mask = BIT(1) | BIT(0),
0238     .routes = {
0239         /*
0240          * R8A7779 has two RGB outputs and one (currently unsupported)
0241          * TCON output.
0242          */
0243         [RCAR_DU_OUTPUT_DPAD0] = {
0244             .possible_crtcs = BIT(0),
0245             .port = 0,
0246         },
0247         [RCAR_DU_OUTPUT_DPAD1] = {
0248             .possible_crtcs = BIT(1) | BIT(0),
0249             .port = 1,
0250         },
0251     },
0252 };
0253 
0254 static const struct rcar_du_device_info rcar_du_r8a7790_info = {
0255     .gen = 2,
0256     .features = RCAR_DU_FEATURE_CRTC_IRQ
0257           | RCAR_DU_FEATURE_CRTC_CLOCK
0258           | RCAR_DU_FEATURE_INTERLACED
0259           | RCAR_DU_FEATURE_TVM_SYNC,
0260     .quirks = RCAR_DU_QUIRK_ALIGN_128B,
0261     .channels_mask = BIT(2) | BIT(1) | BIT(0),
0262     .routes = {
0263         /*
0264          * R8A7742 and R8A7790 each have one RGB output and two LVDS
0265          * outputs. Additionally R8A7790 supports one TCON output
0266          * (currently unsupported by the driver).
0267          */
0268         [RCAR_DU_OUTPUT_DPAD0] = {
0269             .possible_crtcs = BIT(2) | BIT(1) | BIT(0),
0270             .port = 0,
0271         },
0272         [RCAR_DU_OUTPUT_LVDS0] = {
0273             .possible_crtcs = BIT(0),
0274             .port = 1,
0275         },
0276         [RCAR_DU_OUTPUT_LVDS1] = {
0277             .possible_crtcs = BIT(2) | BIT(1),
0278             .port = 2,
0279         },
0280     },
0281     .num_lvds = 2,
0282     .num_rpf = 4,
0283 };
0284 
0285 /* M2-W (r8a7791) and M2-N (r8a7793) are identical */
0286 static const struct rcar_du_device_info rcar_du_r8a7791_info = {
0287     .gen = 2,
0288     .features = RCAR_DU_FEATURE_CRTC_IRQ
0289           | RCAR_DU_FEATURE_CRTC_CLOCK
0290           | RCAR_DU_FEATURE_INTERLACED
0291           | RCAR_DU_FEATURE_TVM_SYNC,
0292     .channels_mask = BIT(1) | BIT(0),
0293     .routes = {
0294         /*
0295          * R8A779[13] has one RGB output, one LVDS output and one
0296          * (currently unsupported) TCON output.
0297          */
0298         [RCAR_DU_OUTPUT_DPAD0] = {
0299             .possible_crtcs = BIT(1) | BIT(0),
0300             .port = 0,
0301         },
0302         [RCAR_DU_OUTPUT_LVDS0] = {
0303             .possible_crtcs = BIT(0),
0304             .port = 1,
0305         },
0306     },
0307     .num_lvds = 1,
0308     .num_rpf = 4,
0309 };
0310 
0311 static const struct rcar_du_device_info rcar_du_r8a7792_info = {
0312     .gen = 2,
0313     .features = RCAR_DU_FEATURE_CRTC_IRQ
0314           | RCAR_DU_FEATURE_CRTC_CLOCK
0315           | RCAR_DU_FEATURE_INTERLACED
0316           | RCAR_DU_FEATURE_TVM_SYNC,
0317     .channels_mask = BIT(1) | BIT(0),
0318     .routes = {
0319         /* R8A7792 has two RGB outputs. */
0320         [RCAR_DU_OUTPUT_DPAD0] = {
0321             .possible_crtcs = BIT(0),
0322             .port = 0,
0323         },
0324         [RCAR_DU_OUTPUT_DPAD1] = {
0325             .possible_crtcs = BIT(1),
0326             .port = 1,
0327         },
0328     },
0329     .num_rpf = 4,
0330 };
0331 
0332 static const struct rcar_du_device_info rcar_du_r8a7794_info = {
0333     .gen = 2,
0334     .features = RCAR_DU_FEATURE_CRTC_IRQ
0335           | RCAR_DU_FEATURE_CRTC_CLOCK
0336           | RCAR_DU_FEATURE_INTERLACED
0337           | RCAR_DU_FEATURE_TVM_SYNC,
0338     .channels_mask = BIT(1) | BIT(0),
0339     .routes = {
0340         /*
0341          * R8A7794 has two RGB outputs and one (currently unsupported)
0342          * TCON output.
0343          */
0344         [RCAR_DU_OUTPUT_DPAD0] = {
0345             .possible_crtcs = BIT(0),
0346             .port = 0,
0347         },
0348         [RCAR_DU_OUTPUT_DPAD1] = {
0349             .possible_crtcs = BIT(1),
0350             .port = 1,
0351         },
0352     },
0353     .num_rpf = 4,
0354 };
0355 
0356 static const struct rcar_du_device_info rcar_du_r8a7795_info = {
0357     .gen = 3,
0358     .features = RCAR_DU_FEATURE_CRTC_IRQ
0359           | RCAR_DU_FEATURE_CRTC_CLOCK
0360           | RCAR_DU_FEATURE_VSP1_SOURCE
0361           | RCAR_DU_FEATURE_INTERLACED
0362           | RCAR_DU_FEATURE_TVM_SYNC,
0363     .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
0364     .routes = {
0365         /*
0366          * R8A7795 has one RGB output, two HDMI outputs and one
0367          * LVDS output.
0368          */
0369         [RCAR_DU_OUTPUT_DPAD0] = {
0370             .possible_crtcs = BIT(3),
0371             .port = 0,
0372         },
0373         [RCAR_DU_OUTPUT_HDMI0] = {
0374             .possible_crtcs = BIT(1),
0375             .port = 1,
0376         },
0377         [RCAR_DU_OUTPUT_HDMI1] = {
0378             .possible_crtcs = BIT(2),
0379             .port = 2,
0380         },
0381         [RCAR_DU_OUTPUT_LVDS0] = {
0382             .possible_crtcs = BIT(0),
0383             .port = 3,
0384         },
0385     },
0386     .num_lvds = 1,
0387     .num_rpf = 5,
0388     .dpll_mask =  BIT(2) | BIT(1),
0389 };
0390 
0391 static const struct rcar_du_device_info rcar_du_r8a7796_info = {
0392     .gen = 3,
0393     .features = RCAR_DU_FEATURE_CRTC_IRQ
0394           | RCAR_DU_FEATURE_CRTC_CLOCK
0395           | RCAR_DU_FEATURE_VSP1_SOURCE
0396           | RCAR_DU_FEATURE_INTERLACED
0397           | RCAR_DU_FEATURE_TVM_SYNC,
0398     .channels_mask = BIT(2) | BIT(1) | BIT(0),
0399     .routes = {
0400         /*
0401          * R8A7796 has one RGB output, one LVDS output and one HDMI
0402          * output.
0403          */
0404         [RCAR_DU_OUTPUT_DPAD0] = {
0405             .possible_crtcs = BIT(2),
0406             .port = 0,
0407         },
0408         [RCAR_DU_OUTPUT_HDMI0] = {
0409             .possible_crtcs = BIT(1),
0410             .port = 1,
0411         },
0412         [RCAR_DU_OUTPUT_LVDS0] = {
0413             .possible_crtcs = BIT(0),
0414             .port = 2,
0415         },
0416     },
0417     .num_lvds = 1,
0418     .num_rpf = 5,
0419     .dpll_mask =  BIT(1),
0420 };
0421 
0422 static const struct rcar_du_device_info rcar_du_r8a77965_info = {
0423     .gen = 3,
0424     .features = RCAR_DU_FEATURE_CRTC_IRQ
0425           | RCAR_DU_FEATURE_CRTC_CLOCK
0426           | RCAR_DU_FEATURE_VSP1_SOURCE
0427           | RCAR_DU_FEATURE_INTERLACED
0428           | RCAR_DU_FEATURE_TVM_SYNC,
0429     .channels_mask = BIT(3) | BIT(1) | BIT(0),
0430     .routes = {
0431         /*
0432          * R8A77965 has one RGB output, one LVDS output and one HDMI
0433          * output.
0434          */
0435         [RCAR_DU_OUTPUT_DPAD0] = {
0436             .possible_crtcs = BIT(2),
0437             .port = 0,
0438         },
0439         [RCAR_DU_OUTPUT_HDMI0] = {
0440             .possible_crtcs = BIT(1),
0441             .port = 1,
0442         },
0443         [RCAR_DU_OUTPUT_LVDS0] = {
0444             .possible_crtcs = BIT(0),
0445             .port = 2,
0446         },
0447     },
0448     .num_lvds = 1,
0449     .num_rpf = 5,
0450     .dpll_mask =  BIT(1),
0451 };
0452 
0453 static const struct rcar_du_device_info rcar_du_r8a77970_info = {
0454     .gen = 3,
0455     .features = RCAR_DU_FEATURE_CRTC_IRQ
0456           | RCAR_DU_FEATURE_CRTC_CLOCK
0457           | RCAR_DU_FEATURE_VSP1_SOURCE
0458           | RCAR_DU_FEATURE_INTERLACED
0459           | RCAR_DU_FEATURE_TVM_SYNC,
0460     .channels_mask = BIT(0),
0461     .routes = {
0462         /*
0463          * R8A77970 and R8A77980 have one RGB output and one LVDS
0464          * output.
0465          */
0466         [RCAR_DU_OUTPUT_DPAD0] = {
0467             .possible_crtcs = BIT(0),
0468             .port = 0,
0469         },
0470         [RCAR_DU_OUTPUT_LVDS0] = {
0471             .possible_crtcs = BIT(0),
0472             .port = 1,
0473         },
0474     },
0475     .num_lvds = 1,
0476     .num_rpf = 5,
0477 };
0478 
0479 static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
0480     .gen = 3,
0481     .features = RCAR_DU_FEATURE_CRTC_IRQ
0482           | RCAR_DU_FEATURE_CRTC_CLOCK
0483           | RCAR_DU_FEATURE_VSP1_SOURCE,
0484     .channels_mask = BIT(1) | BIT(0),
0485     .routes = {
0486         /*
0487          * R8A77990 and R8A77995 have one RGB output and two LVDS
0488          * outputs.
0489          */
0490         [RCAR_DU_OUTPUT_DPAD0] = {
0491             .possible_crtcs = BIT(0) | BIT(1),
0492             .port = 0,
0493         },
0494         [RCAR_DU_OUTPUT_LVDS0] = {
0495             .possible_crtcs = BIT(0),
0496             .port = 1,
0497         },
0498         [RCAR_DU_OUTPUT_LVDS1] = {
0499             .possible_crtcs = BIT(1),
0500             .port = 2,
0501         },
0502     },
0503     .num_lvds = 2,
0504     .num_rpf = 5,
0505     .lvds_clk_mask =  BIT(1) | BIT(0),
0506 };
0507 
0508 static const struct rcar_du_device_info rcar_du_r8a779a0_info = {
0509     .gen = 3,
0510     .features = RCAR_DU_FEATURE_CRTC_IRQ
0511           | RCAR_DU_FEATURE_VSP1_SOURCE,
0512     .channels_mask = BIT(1) | BIT(0),
0513     .routes = {
0514         /* R8A779A0 has two MIPI DSI outputs. */
0515         [RCAR_DU_OUTPUT_DSI0] = {
0516             .possible_crtcs = BIT(0),
0517             .port = 0,
0518         },
0519         [RCAR_DU_OUTPUT_DSI1] = {
0520             .possible_crtcs = BIT(1),
0521             .port = 1,
0522         },
0523     },
0524     .num_rpf = 5,
0525     .dsi_clk_mask =  BIT(1) | BIT(0),
0526 };
0527 
0528 static const struct of_device_id rcar_du_of_table[] = {
0529     { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info },
0530     { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info },
0531     { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info },
0532     { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info },
0533     { .compatible = "renesas,du-r8a77470", .data = &rzg1_du_r8a77470_info },
0534     { .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info },
0535     { .compatible = "renesas,du-r8a774b1", .data = &rcar_du_r8a774b1_info },
0536     { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info },
0537     { .compatible = "renesas,du-r8a774e1", .data = &rcar_du_r8a774e1_info },
0538     { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
0539     { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
0540     { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
0541     { .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info },
0542     { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
0543     { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
0544     { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
0545     { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
0546     { .compatible = "renesas,du-r8a77961", .data = &rcar_du_r8a7796_info },
0547     { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info },
0548     { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info },
0549     { .compatible = "renesas,du-r8a77980", .data = &rcar_du_r8a77970_info },
0550     { .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info },
0551     { .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info },
0552     { .compatible = "renesas,du-r8a779a0", .data = &rcar_du_r8a779a0_info },
0553     { }
0554 };
0555 
0556 MODULE_DEVICE_TABLE(of, rcar_du_of_table);
0557 
0558 const char *rcar_du_output_name(enum rcar_du_output output)
0559 {
0560     static const char * const names[] = {
0561         [RCAR_DU_OUTPUT_DPAD0] = "DPAD0",
0562         [RCAR_DU_OUTPUT_DPAD1] = "DPAD1",
0563         [RCAR_DU_OUTPUT_DSI0] = "DSI0",
0564         [RCAR_DU_OUTPUT_DSI1] = "DSI1",
0565         [RCAR_DU_OUTPUT_HDMI0] = "HDMI0",
0566         [RCAR_DU_OUTPUT_HDMI1] = "HDMI1",
0567         [RCAR_DU_OUTPUT_LVDS0] = "LVDS0",
0568         [RCAR_DU_OUTPUT_LVDS1] = "LVDS1",
0569         [RCAR_DU_OUTPUT_TCON] = "TCON",
0570     };
0571 
0572     if (output >= ARRAY_SIZE(names) || !names[output])
0573         return "UNKNOWN";
0574 
0575     return names[output];
0576 }
0577 
0578 /* -----------------------------------------------------------------------------
0579  * DRM operations
0580  */
0581 
0582 DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
0583 
0584 static const struct drm_driver rcar_du_driver = {
0585     .driver_features    = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
0586     .dumb_create        = rcar_du_dumb_create,
0587     .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
0588     .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
0589     .gem_prime_import_sg_table = rcar_du_gem_prime_import_sg_table,
0590     .gem_prime_mmap     = drm_gem_prime_mmap,
0591     .fops           = &rcar_du_fops,
0592     .name           = "rcar-du",
0593     .desc           = "Renesas R-Car Display Unit",
0594     .date           = "20130110",
0595     .major          = 1,
0596     .minor          = 0,
0597 };
0598 
0599 /* -----------------------------------------------------------------------------
0600  * Power management
0601  */
0602 
0603 #ifdef CONFIG_PM_SLEEP
0604 static int rcar_du_pm_suspend(struct device *dev)
0605 {
0606     struct rcar_du_device *rcdu = dev_get_drvdata(dev);
0607 
0608     return drm_mode_config_helper_suspend(&rcdu->ddev);
0609 }
0610 
0611 static int rcar_du_pm_resume(struct device *dev)
0612 {
0613     struct rcar_du_device *rcdu = dev_get_drvdata(dev);
0614 
0615     return drm_mode_config_helper_resume(&rcdu->ddev);
0616 }
0617 #endif
0618 
0619 static const struct dev_pm_ops rcar_du_pm_ops = {
0620     SET_SYSTEM_SLEEP_PM_OPS(rcar_du_pm_suspend, rcar_du_pm_resume)
0621 };
0622 
0623 /* -----------------------------------------------------------------------------
0624  * Platform driver
0625  */
0626 
0627 static int rcar_du_remove(struct platform_device *pdev)
0628 {
0629     struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
0630     struct drm_device *ddev = &rcdu->ddev;
0631 
0632     drm_dev_unregister(ddev);
0633     drm_atomic_helper_shutdown(ddev);
0634 
0635     drm_kms_helper_poll_fini(ddev);
0636 
0637     return 0;
0638 }
0639 
0640 static void rcar_du_shutdown(struct platform_device *pdev)
0641 {
0642     struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
0643 
0644     drm_atomic_helper_shutdown(&rcdu->ddev);
0645 }
0646 
0647 static int rcar_du_probe(struct platform_device *pdev)
0648 {
0649     struct rcar_du_device *rcdu;
0650     unsigned int mask;
0651     int ret;
0652 
0653     if (drm_firmware_drivers_only())
0654         return -ENODEV;
0655 
0656     /* Allocate and initialize the R-Car device structure. */
0657     rcdu = devm_drm_dev_alloc(&pdev->dev, &rcar_du_driver,
0658                   struct rcar_du_device, ddev);
0659     if (IS_ERR(rcdu))
0660         return PTR_ERR(rcdu);
0661 
0662     rcdu->dev = &pdev->dev;
0663     rcdu->info = of_device_get_match_data(rcdu->dev);
0664 
0665     platform_set_drvdata(pdev, rcdu);
0666 
0667     /* I/O resources */
0668     rcdu->mmio = devm_platform_ioremap_resource(pdev, 0);
0669     if (IS_ERR(rcdu->mmio))
0670         return PTR_ERR(rcdu->mmio);
0671 
0672     /*
0673      * Set the DMA coherent mask to reflect the DU 32-bit DMA address space
0674      * limitations. When sourcing frames from a VSP the DU doesn't perform
0675      * any memory access so set the mask to 40 bits to accept all buffers.
0676      */
0677     mask = rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE) ? 40 : 32;
0678     ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(mask));
0679     if (ret)
0680         return ret;
0681 
0682     /* DRM/KMS objects */
0683     ret = rcar_du_modeset_init(rcdu);
0684     if (ret < 0) {
0685         if (ret != -EPROBE_DEFER)
0686             dev_err(&pdev->dev,
0687                 "failed to initialize DRM/KMS (%d)\n", ret);
0688         goto error;
0689     }
0690 
0691     /*
0692      * Register the DRM device with the core and the connectors with
0693      * sysfs.
0694      */
0695     ret = drm_dev_register(&rcdu->ddev, 0);
0696     if (ret)
0697         goto error;
0698 
0699     DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
0700 
0701     drm_fbdev_generic_setup(&rcdu->ddev, 32);
0702 
0703     return 0;
0704 
0705 error:
0706     drm_kms_helper_poll_fini(&rcdu->ddev);
0707     return ret;
0708 }
0709 
0710 static struct platform_driver rcar_du_platform_driver = {
0711     .probe      = rcar_du_probe,
0712     .remove     = rcar_du_remove,
0713     .shutdown   = rcar_du_shutdown,
0714     .driver     = {
0715         .name   = "rcar-du",
0716         .pm = &rcar_du_pm_ops,
0717         .of_match_table = rcar_du_of_table,
0718     },
0719 };
0720 
0721 module_platform_driver(rcar_du_platform_driver);
0722 
0723 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
0724 MODULE_DESCRIPTION("Renesas R-Car Display Unit DRM Driver");
0725 MODULE_LICENSE("GPL");