drm: rcar-du: Add R8A7795 device support
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Mon, 7 Sep 2015 14:34:26 +0000 (17:34 +0300)
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tue, 23 Feb 2016 07:34:29 +0000 (09:34 +0200)
Document the R8A7795-specific DT bindings and support them in the
driver. The HDMI and LVDS outputs are currently not supported.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Documentation/devicetree/bindings/display/renesas,du.txt
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rcar-du/rcar_du_drv.h
drivers/gpu/drm/rcar-du/rcar_du_group.c
drivers/gpu/drm/rcar-du/rcar_du_kms.c
drivers/gpu/drm/rcar-du/rcar_du_plane.c
drivers/gpu/drm/rcar-du/rcar_du_regs.h
drivers/gpu/drm/rcar-du/rcar_du_vsp.c

index eccd4f4867b29cd9e5a1c6fee231fadfb79b5e8e..0d30e42e40bea1512428f0d7c15910f5daae7a19 100644 (file)
@@ -8,6 +8,7 @@ Required Properties:
     - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
     - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
     - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
+    - "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
 
   - reg: A list of base address and length of each memory resource, one for
     each entry in the reg-names property.
@@ -24,7 +25,7 @@ Required Properties:
   - clock-names: Name of the clocks. This property is model-dependent.
     - R8A7779 uses a single functional clock. The clock doesn't need to be
       named.
-    - R8A779[0134] use one functional clock per channel and one clock per LVDS
+    - R8A779[01345] use one functional clock per channel and one clock per LVDS
       encoder (if available). The functional clocks must be named "du.x" with
       "x" being the channel numerical index. The LVDS clocks must be named
       "lvds.x" with "x" being the LVDS encoder numerical index.
@@ -41,13 +42,14 @@ bindings specified in Documentation/devicetree/bindings/graph.txt.
 The following table lists for each supported model the port number
 corresponding to each DU output.
 
-               Port 0          Port1           Port2
+               Port 0          Port1           Port2           Port3
 -----------------------------------------------------------------------------
- R8A7779 (H1)  DPAD 0          DPAD 1          -
- R8A7790 (H2)  DPAD            LVDS 0          LVDS 1
- R8A7791 (M2-W)        DPAD            LVDS 0          -
- R8A7793 (M2-N)        DPAD            LVDS 0          -
- R8A7794 (E2)  DPAD 0          DPAD 1          -
+ R8A7779 (H1)  DPAD 0          DPAD 1          -               -
+ R8A7790 (H2)  DPAD            LVDS 0          LVDS 1          -
+ R8A7791 (M2-W)        DPAD            LVDS 0          -               -
+ R8A7793 (M2-N)        DPAD            LVDS 0          -               -
+ R8A7794 (E2)  DPAD 0          DPAD 1          -               -
+ R8A7795 (H3)  DPAD            HDMI 0          HDMI 1          LVDS
 
 
 Example: R8A7790 (R-Car H2) DU
index 814fb0ad86dce7edbc9dd1167db542bdecfa6c3c..51e9e8ce551ade6d56a64cd2f54b0caea800ea88 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * rcar_du_crtc.c  --  R-Car Display Unit CRTCs
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -254,8 +254,13 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 
        /* If VSP+DU integration is enabled the plane assignment is fixed. */
        if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
-               dspr = (rcrtc->index % 2) + 1;
-               hwplanes = 1 << (rcrtc->index % 2);
+               if (rcdu->info->gen < 3) {
+                       dspr = (rcrtc->index % 2) + 1;
+                       hwplanes = 1 << (rcrtc->index % 2);
+               } else {
+                       dspr = (rcrtc->index % 2) ? 3 : 1;
+                       hwplanes = 1 << ((rcrtc->index % 2) ? 2 : 0);
+               }
        }
 
        /* Update the planes to display timing and dot clock generator
index aad553329d9f1aa409caef4451abee106b6c8a98..24265d75e7deb54a01b74dac06ac9cb641c8327e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * rcar_du_drv.c  --  R-Car Display Unit DRM driver
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -36,6 +36,7 @@
  */
 
 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
+       .gen = 2,
        .features = 0,
        .num_crtcs = 2,
        .routes = {
@@ -57,6 +58,7 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 };
 
 static const struct rcar_du_device_info rcar_du_r8a7790_info = {
+       .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
                  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
        .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
@@ -86,6 +88,7 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
 
 /* M2-W (r8a7791) and M2-N (r8a7793) are identical */
 static const struct rcar_du_device_info rcar_du_r8a7791_info = {
+       .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
                  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
        .num_crtcs = 2,
@@ -108,6 +111,7 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 };
 
 static const struct rcar_du_device_info rcar_du_r8a7794_info = {
+       .gen = 2,
        .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
                  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
        .num_crtcs = 2,
@@ -129,12 +133,31 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
        .num_lvds = 0,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7795_info = {
+       .gen = 3,
+       .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+                 | RCAR_DU_FEATURE_EXT_CTRL_REGS
+                 | RCAR_DU_FEATURE_VSP1_SOURCE,
+       .num_crtcs = 4,
+       .routes = {
+               /* R8A7795 has one RGB output, and two HDMI and one LVDS
+                * (currently unsupported) outputs
+                */
+               [RCAR_DU_OUTPUT_DPAD0] = {
+                       .possible_crtcs = BIT(3),
+                       .encoder_type = DRM_MODE_ENCODER_NONE,
+                       .port = 0,
+               },
+       },
+};
+
 static const struct of_device_id rcar_du_of_table[] = {
        { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
        { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
        { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
        { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
        { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
+       { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
        { }
 };
 
index ce359edc9ab9e92b8086543391f53566cc3c0a8a..ed35467d96cfd568a8668202aa3364ddefeed380 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * rcar_du_drv.h  --  R-Car Display Unit DRM driver
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -53,6 +53,7 @@ struct rcar_du_output_routing {
 
 /*
  * struct rcar_du_device_info - DU model-specific information
+ * @gen: device generation (2 or 3)
  * @features: device features (RCAR_DU_FEATURE_*)
  * @quirks: device quirks (RCAR_DU_QUIRK_*)
  * @num_crtcs: total number of CRTCs
@@ -60,6 +61,7 @@ struct rcar_du_output_routing {
  * @num_lvds: number of internal LVDS encoders
  */
 struct rcar_du_device_info {
+       unsigned int gen;
        unsigned int features;
        unsigned int quirks;
        unsigned int num_crtcs;
index 144d1e0a7a4ac0147b13024feaa1e1124f653071..33b2fc53da3e3e35eefd7c71d6e07df483fa3f10 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * rcar_du_group.c  --  R-Car Display Unit Channels Pair
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -56,17 +56,32 @@ static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
 
 static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 {
-       u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
+       struct rcar_du_device *rcdu = rgrp->dev;
+       unsigned int possible_crtcs =
+               rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
+       u32 defr8 = DEFR8_CODE;
 
-       /* The DEFR8 register for the first group also controls RGB output
-        * routing to DPAD0 and VSPD1 routing to DU0/1/2 for DU instances that
-        * support it.
-        */
-       if (rgrp->index == 0) {
-               if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1)
-                       defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
-               if (rgrp->dev->vspd1_sink == 2)
-                       defr8 |= DEFR8_VSCS;
+       if (rcdu->info->gen < 3) {
+               defr8 |= DEFR8_DEFE8;
+
+               /* On Gen2 the DEFR8 register for the first group also controls
+                * RGB output routing to DPAD0 and VSPD1 routing to DU0/1/2 for
+                * DU instances that support it.
+                */
+               if (rgrp->index == 0) {
+                       if (possible_crtcs > 1)
+                               defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
+                       if (rgrp->dev->vspd1_sink == 2)
+                               defr8 |= DEFR8_VSCS;
+               }
+       } else {
+               /* On Gen3 VSPD routing can't be configured, but DPAD routing
+                * needs to be set despite having a single option available.
+                */
+               u32 crtc = ffs(possible_crtcs) - 1;
+
+               if (crtc / 2 == rgrp->index)
+                       defr8 |= DEFR8_DRGBS_DU(crtc);
        }
 
        rcar_du_group_write(rgrp, DEFR8, defr8);
@@ -74,11 +89,15 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 
 static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 {
+       struct rcar_du_device *rcdu = rgrp->dev;
+
        /* Enable extended features */
        rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE);
-       rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
-       rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
-       rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
+       if (rcdu->info->gen < 3) {
+               rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
+               rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
+               rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
+       }
        rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
 
        rcar_du_group_setup_pins(rgrp);
@@ -98,6 +117,9 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
                                    DIDSR_PDCS_CLK(0, 0));
        }
 
+       if (rcdu->info->gen >= 3)
+               rcar_du_group_write(rgrp, DEFR10, DEFR10_CODE | DEFR10_DEFE10);
+
        /* Use DS1PR and DS2PR to configure planes priorities and connects the
         * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
         */
index 43a53ad0841cb2089e0d3ceee365a69874eec208..7d65251d3df052b57dca8d61f54d9417f860f451 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * rcar_du_kms.c  --  R-Car Display Unit Mode Setting
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -544,10 +544,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
                rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U);
 
                /* If we have more than one CRTCs in this group pre-associate
-                * planes 0-3 with CRTC 0 and planes 4-7 with CRTC 1 to minimize
-                * flicker occurring when the association is changed.
+                * the low-order planes with CRTC 0 and the high-order planes
+                * with CRTC 1 to minimize flicker occurring when the
+                * association is changed.
                 */
-               rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0;
+               rgrp->dptsr_planes = rgrp->num_crtcs > 1
+                                  ? (rcdu->info->gen >= 3 ? 0x04 : 0xf0)
+                                  : 0;
 
                if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
                        ret = rcar_du_planes_init(rgrp);
index 78216f3623859aca071e4c796473850b2ca7e5f0..8460ae1ffa4bbfbea57a29d309da7c226e46f7d6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * rcar_du_plane.c  --  R-Car Display Unit Planes
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -454,9 +454,9 @@ static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
        }
 }
 
-static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
-                                      unsigned int index,
-                                      const struct rcar_du_plane_state *state)
+static void rcar_du_plane_setup_format_gen2(struct rcar_du_group *rgrp,
+                                           unsigned int index,
+                                           const struct rcar_du_plane_state *state)
 {
        u32 ddcr2 = PnDDCR2_CODE;
        u32 ddcr4;
@@ -491,6 +491,29 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
                ddcr4 |= PnDDCR4_VSPS;
 
        rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
+}
+
+static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
+                                           unsigned int index,
+                                           const struct rcar_du_plane_state *state)
+{
+       rcar_du_plane_write(rgrp, index, PnMR,
+                           PnMR_SPIM_TP_OFF | state->format->pnmr);
+
+       rcar_du_plane_write(rgrp, index, PnDDCR4,
+                           state->format->edf | PnDDCR4_CODE);
+}
+
+static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
+                                      unsigned int index,
+                                      const struct rcar_du_plane_state *state)
+{
+       struct rcar_du_device *rcdu = rgrp->dev;
+
+       if (rcdu->info->gen < 3)
+               rcar_du_plane_setup_format_gen2(rgrp, index, state);
+       else
+               rcar_du_plane_setup_format_gen3(rgrp, index, state);
 
        /* Destination position and size */
        rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
@@ -498,26 +521,30 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
        rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
        rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);
 
-       /* Wrap-around and blinking, disabled */
-       rcar_du_plane_write(rgrp, index, PnWASPR, 0);
-       rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
-       rcar_du_plane_write(rgrp, index, PnBTR, 0);
-       rcar_du_plane_write(rgrp, index, PnMLR, 0);
+       if (rcdu->info->gen < 3) {
+               /* Wrap-around and blinking, disabled */
+               rcar_du_plane_write(rgrp, index, PnWASPR, 0);
+               rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
+               rcar_du_plane_write(rgrp, index, PnBTR, 0);
+               rcar_du_plane_write(rgrp, index, PnMLR, 0);
+       }
 }
 
 void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
                           const struct rcar_du_plane_state *state)
 {
+       struct rcar_du_device *rcdu = rgrp->dev;
+
        rcar_du_plane_setup_format(rgrp, state->hwindex, state);
        if (state->format->planes == 2)
                rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
                                           state);
 
-       rcar_du_plane_setup_scanout(rgrp, state);
+       if (rcdu->info->gen < 3)
+               rcar_du_plane_setup_scanout(rgrp, state);
 
        if (state->source == RCAR_DU_PLANE_VSPD1) {
                unsigned int vspd1_sink = rgrp->index ? 2 : 0;
-               struct rcar_du_device *rcdu = rgrp->dev;
 
                if (rcdu->vspd1_sink != vspd1_sink) {
                        rcdu->vspd1_sink = vspd1_sink;
index 2ccb1a241fc4d2270341abf550a408afce67311d..d2f66068e52c01c49d798a29c42c752163f15b18 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * rcar_du_regs.h  --  R-Car Display Unit Registers Definitions
  *
- * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
 #define DIDSR_PDCS_CLK(n, clk) (clk << ((n) * 2))
 #define DIDSR_PDCS_MASK(n)     (3 << ((n) * 2))
 
+#define DEFR10                 0x20038
+#define DEFR10_CODE            (0x7795 << 16)
+#define DEFR10_VSPF1_RGB       (0 << 14)
+#define DEFR10_VSPF1_YC                (1 << 14)
+#define DEFR10_DOCF1_RGB       (0 << 12)
+#define DEFR10_DOCF1_YC                (1 << 12)
+#define DEFR10_YCDF0_YCBCR444  (0 << 11)
+#define DEFR10_YCDF0_YCBCR422  (1 << 11)
+#define DEFR10_VSPF0_RGB       (0 << 10)
+#define DEFR10_VSPF0_YC                (1 << 10)
+#define DEFR10_DOCF0_RGB       (0 << 8)
+#define DEFR10_DOCF0_YC                (1 << 8)
+#define DEFR10_TSEL_H3_TCON1   (0 << 1) /* DEFR102 register only (DU2/DU3) */
+#define DEFR10_DEFE10          (1 << 0)
+
 /* -----------------------------------------------------------------------------
  * Display Timing Generation Registers
  */
index 7c7d6f265a0995f935db0c9be705071233291097..24acee1633e90d6dba09598bf8c6af94e647a61e 100644 (file)
@@ -31,6 +31,7 @@
 void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
 {
        const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
+       struct rcar_du_device *rcdu = crtc->group->dev;
        struct rcar_du_plane_state state = {
                .state = {
                        .crtc = &crtc->crtc,
@@ -44,13 +45,17 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
                        .src_h = mode->vdisplay << 16,
                },
                .format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
-               .hwindex = crtc->index % 2,
                .source = RCAR_DU_PLANE_VSPD1,
                .alpha = 255,
                .colorkey = 0,
                .zpos = 0,
        };
 
+       if (rcdu->info->gen >= 3)
+               state.hwindex = (crtc->index % 2) ? 2 : 0;
+       else
+               state.hwindex = crtc->index % 2;
+
        __rcar_du_plane_setup(crtc->group, &state);
 
        /* Ensure that the plane source configuration takes effect by requesting
@@ -329,10 +334,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
                return ret;
 
         /* The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to
-         * 4 RPFs. Hardcode the number of planes to 4 as Gen3 isn't supported
-         * yet.
+         * 4 RPFs.
          */
-       vsp->num_planes = 4;
+       vsp->num_planes = rcdu->info->gen >= 3 ? 5 : 4;
 
        vsp->planes = devm_kcalloc(rcdu->dev, vsp->num_planes,
                                   sizeof(*vsp->planes), GFP_KERNEL);