#include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
+#include "rcar_du_encoder.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
        rcar_du_crtc_write(rcrtc, DEWR,  mode->hdisplay);
 }
 
-void rcar_du_crtc_route_output(struct drm_crtc *crtc,
-                              enum rcar_du_output output)
-{
-       struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
-       struct rcar_du_device *rcdu = rcrtc->group->dev;
-
-       /*
-        * Store the route from the CRTC output to the DU output. The DU will be
-        * configured when starting the CRTC.
-        */
-       rcrtc->outputs |= BIT(output);
-
-       /*
-        * Store RGB routing to DPAD0, the hardware will be configured when
-        * starting the CRTC.
-        */
-       if (output == RCAR_DU_OUTPUT_DPAD0)
-               rcdu->dpad0_source = rcrtc->index;
-}
-
 static unsigned int plane_zpos(struct rcar_du_plane *plane)
 {
        return plane->plane.state->normalized_zpos;
  * CRTC Functions
  */
 
+static int rcar_du_crtc_atomic_check(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *state)
+{
+       struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(state);
+       struct drm_encoder *encoder;
+
+       /* Store the routes from the CRTC output to the DU outputs. */
+       rstate->outputs = 0;
+
+       drm_for_each_encoder_mask(encoder, crtc->dev, state->encoder_mask) {
+               struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
+
+               rstate->outputs |= BIT(renc->output);
+       }
+
+       return 0;
+}
+
 static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
                                       struct drm_crtc_state *old_state)
 {
                crtc->state->event = NULL;
        }
        spin_unlock_irq(&crtc->dev->event_lock);
-
-       rcrtc->outputs = 0;
 }
 
 static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
 }
 
 static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
+       .atomic_check = rcar_du_crtc_atomic_check,
        .atomic_begin = rcar_du_crtc_atomic_begin,
        .atomic_flush = rcar_du_crtc_atomic_flush,
        .atomic_enable = rcar_du_crtc_atomic_enable,
 
  * @vblank_lock: protects vblank_wait and vblank_count
  * @vblank_wait: wait queue used to signal vertical blanking
  * @vblank_count: number of vertical blanking interrupts to wait for
- * @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC
  * @group: CRTC group this CRTC belongs to
  * @vsp: VSP feeding video to this CRTC
  * @vsp_pipe: index of the VSP pipeline feeding video to this CRTC
        wait_queue_head_t vblank_wait;
        unsigned int vblank_count;
 
-       unsigned int outputs;
-
        struct rcar_du_group *group;
        struct rcar_du_vsp *vsp;
        unsigned int vsp_pipe;
  * struct rcar_du_crtc_state - Driver-specific CRTC state
  * @state: base DRM CRTC state
  * @crc: CRC computation configuration
+ * @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC
  */
 struct rcar_du_crtc_state {
        struct drm_crtc_state state;
 
        struct vsp1_du_crc_config crc;
+       unsigned int outputs;
 };
 
 #define to_rcar_crtc_state(s) container_of(s, struct rcar_du_crtc_state, state)
 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
 void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
 
-void rcar_du_crtc_route_output(struct drm_crtc *crtc,
-                              enum rcar_du_output output);
 void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc);
 
 void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set);
 
        } props;
 
        unsigned int dpad0_source;
+       unsigned int dpad1_source;
        unsigned int vspd1_sink;
 };
 
 
  * Encoder
  */
 
-static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
-                                    struct drm_crtc_state *crtc_state,
-                                    struct drm_connector_state *conn_state)
-{
-       struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
-
-       rcar_du_crtc_route_output(crtc_state->crtc, renc->output);
-}
-
 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-       .atomic_mode_set = rcar_du_encoder_mode_set,
 };
 
 static const struct drm_encoder_funcs encoder_funcs = {
 
 
 int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
 {
-       struct rcar_du_crtc *crtc0 = &rgrp->dev->crtcs[rgrp->index * 2];
+       struct rcar_du_device *rcdu = rgrp->dev;
        u32 dorcr = rcar_du_group_read(rgrp, DORCR);
 
        dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK);
         * CRTC 1 in all other cases to avoid cloning CRTC 0 to DPAD0 and DPAD1
         * by default.
         */
-       if (crtc0->outputs & BIT(RCAR_DU_OUTPUT_DPAD1))
+       if (rcdu->dpad1_source == rgrp->index * 2)
                dorcr |= DORCR_PG2D_DS1;
        else
                dorcr |= DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_DS2;
 
 static void rcar_du_atomic_commit_tail(struct drm_atomic_state *old_state)
 {
        struct drm_device *dev = old_state->dev;
+       struct rcar_du_device *rcdu = dev->dev_private;
+       struct drm_crtc_state *crtc_state;
+       struct drm_crtc *crtc;
+       unsigned int i;
+
+       /*
+        * Store RGB routing to DPAD0 and DPAD1, the hardware will be configured
+        * when starting the CRTCs.
+        */
+       rcdu->dpad1_source = -1;
+
+       for_each_new_crtc_in_state(old_state, crtc, crtc_state, i) {
+               struct rcar_du_crtc_state *rcrtc_state =
+                       to_rcar_crtc_state(crtc_state);
+               struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+
+               if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD0))
+                       rcdu->dpad0_source = rcrtc->index;
+
+               if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD1))
+                       rcdu->dpad1_source = rcrtc->index;
+       }
 
        /* Apply the atomic update. */
        drm_atomic_helper_commit_modeset_disables(dev, old_state);