struct sun8i_mixer *mixer;
        struct resource *res;
        void __iomem *regs;
+       unsigned int base;
        int plane_cnt;
        int i, ret;
 
 
        list_add_tail(&mixer->engine.list, &drv->engine_list);
 
+       base = sun8i_blender_base(mixer);
+
        /* Reset the registers */
        for (i = 0x0; i < 0x20000; i += 4)
                regmap_write(mixer->engine.regs, i, 0);
                     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
 
        /* Set background color to black */
-       regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR,
+       regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
                     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
        /*
         * Set fill color of bottom plane to black. Generally not needed
         * except when VI plane is at bottom (zpos = 0) and enabled.
         */
-       regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL,
+       regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
                     SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
-       regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
+       regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
                     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
        plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
        for (i = 0; i < plane_cnt; i++)
-               regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(i),
+               regmap_write(mixer->engine.regs,
+                            SUN8I_MIXER_BLEND_MODE(base, i),
                             SUN8I_MIXER_BLEND_MODE_DEF);
 
-       regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL,
+       regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
                           SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
 
        return 0;
 
 
 #define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE                BIT(0)
 
-#define SUN8I_MIXER_BLEND_PIPE_CTL             0x1000
-#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)       (0x1004 + 0x10 * (x) + 0x0)
-#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)       (0x1004 + 0x10 * (x) + 0x4)
-#define SUN8I_MIXER_BLEND_ATTR_COORD(x)                (0x1004 + 0x10 * (x) + 0x8)
-#define SUN8I_MIXER_BLEND_ROUTE                        0x1080
-#define SUN8I_MIXER_BLEND_PREMULTIPLY          0x1084
-#define SUN8I_MIXER_BLEND_BKCOLOR              0x1088
-#define SUN8I_MIXER_BLEND_OUTSIZE              0x108c
-#define SUN8I_MIXER_BLEND_MODE(x)              (0x1090 + 0x04 * (x))
-#define SUN8I_MIXER_BLEND_CK_CTL               0x10b0
-#define SUN8I_MIXER_BLEND_CK_CFG               0x10b4
-#define SUN8I_MIXER_BLEND_CK_MAX(x)            (0x10c0 + 0x04 * (x))
-#define SUN8I_MIXER_BLEND_CK_MIN(x)            (0x10e0 + 0x04 * (x))
-#define SUN8I_MIXER_BLEND_OUTCTL               0x10fc
+#define DE2_BLD_BASE                           0x1000
+#define DE2_CH_BASE                            0x2000
+#define DE2_CH_SIZE                            0x1000
+
+#define SUN8I_MIXER_BLEND_PIPE_CTL(base)       ((base) + 0)
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, x) ((base) + 0x4 + 0x10 * (x))
+#define SUN8I_MIXER_BLEND_ATTR_INSIZE(base, x) ((base) + 0x8 + 0x10 * (x))
+#define SUN8I_MIXER_BLEND_ATTR_COORD(base, x)  ((base) + 0xc + 0x10 * (x))
+#define SUN8I_MIXER_BLEND_ROUTE(base)          ((base) + 0x80)
+#define SUN8I_MIXER_BLEND_PREMULTIPLY(base)    ((base) + 0x84)
+#define SUN8I_MIXER_BLEND_BKCOLOR(base)                ((base) + 0x88)
+#define SUN8I_MIXER_BLEND_OUTSIZE(base)                ((base) + 0x8c)
+#define SUN8I_MIXER_BLEND_MODE(base, x)                ((base) + 0x90 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_CTL(base)         ((base) + 0xb0)
+#define SUN8I_MIXER_BLEND_CK_CFG(base)         ((base) + 0xb4)
+#define SUN8I_MIXER_BLEND_CK_MAX(base, x)      ((base) + 0xc0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_MIN(base, x)      ((base) + 0xe0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_OUTCTL(base)         ((base) + 0xfc)
 
 #define SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK      GENMASK(12, 8)
 #define SUN8I_MIXER_BLEND_PIPE_CTL_EN(pipe)    BIT(8 + pipe)
        return container_of(engine, struct sun8i_mixer, engine);
 }
 
+static inline u32
+sun8i_blender_base(struct sun8i_mixer *mixer)
+{
+       return DE2_BLD_BASE;
+}
+
+static inline u32
+sun8i_channel_base(struct sun8i_mixer *mixer, int channel)
+{
+       return DE2_CH_BASE + channel * DE2_CH_SIZE;
+}
+
 const struct de2_fmt_info *sun8i_mixer_format_info(u32 format);
 #endif /* _SUN8I_MIXER_H_ */
 
                                  int overlay, bool enable, unsigned int zpos,
                                  unsigned int old_zpos)
 {
-       u32 val;
+       u32 val, bld_base, ch_base;
+
+       bld_base = sun8i_blender_base(mixer);
+       ch_base = sun8i_channel_base(mixer, channel);
 
        DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n",
                         enable ? "En" : "Dis", channel, overlay);
                val = 0;
 
        regmap_update_bits(mixer->engine.regs,
-                          SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
+                          SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
                           SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
 
        if (!enable || zpos != old_zpos) {
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_PIPE_CTL,
+                                  SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
                                   SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
                                   0);
 
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_ROUTE,
+                                  SUN8I_MIXER_BLEND_ROUTE(bld_base),
                                   SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
                                   0);
        }
                val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
 
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_PIPE_CTL, val, val);
+                                  SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
+                                  val, val);
 
                val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
 
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_ROUTE,
+                                  SUN8I_MIXER_BLEND_ROUTE(bld_base),
                                   SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
                                   val);
        }
 {
        struct drm_plane_state *state = plane->state;
        u32 src_w, src_h, dst_w, dst_h;
+       u32 bld_base, ch_base;
        u32 outsize, insize;
        u32 hphase, vphase;
 
        DRM_DEBUG_DRIVER("Updating UI channel %d overlay %d\n",
                         channel, overlay);
 
+       bld_base = sun8i_blender_base(mixer);
+       ch_base = sun8i_channel_base(mixer, channel);
+
        src_w = drm_rect_width(&state->src) >> 16;
        src_h = drm_rect_height(&state->src) >> 16;
        dst_w = drm_rect_width(&state->dst);
                regmap_write(mixer->engine.regs,
                             SUN8I_MIXER_GLOBAL_SIZE,
                             outsize);
-               regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
-                            outsize);
+               regmap_write(mixer->engine.regs,
+                            SUN8I_MIXER_BLEND_OUTSIZE(bld_base), outsize);
 
                if (state->crtc)
                        interlaced = state->crtc->state->adjusted_mode.flags
                        val = 0;
 
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_OUTCTL,
+                                  SUN8I_MIXER_BLEND_OUTCTL(bld_base),
                                   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
                                   val);
 
                         state->src.x1 >> 16, state->src.y1 >> 16);
        DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_CHAN_UI_LAYER_SIZE(channel, overlay),
+                    SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch_base, overlay),
                     insize);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel),
+                    SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch_base),
                     insize);
 
        if (insize != outsize || hphase || vphase) {
                         state->dst.x1, state->dst.y1);
        DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_BLEND_ATTR_COORD(zpos),
+                    SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
                     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos),
+                    SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
                     outsize);
 
        return 0;
 {
        struct drm_plane_state *state = plane->state;
        const struct de2_fmt_info *fmt_info;
-       u32 val;
+       u32 val, ch_base;
+
+       ch_base = sun8i_channel_base(mixer, channel);
 
        fmt_info = sun8i_mixer_format_info(state->fb->format->format);
        if (!fmt_info || !fmt_info->rgb) {
 
        val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
        regmap_update_bits(mixer->engine.regs,
-                          SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
+                          SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch_base, overlay),
                           SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
 
        return 0;
        struct drm_framebuffer *fb = state->fb;
        struct drm_gem_cma_object *gem;
        dma_addr_t paddr;
+       u32 ch_base;
        int bpp;
 
+       ch_base = sun8i_channel_base(mixer, channel);
+
        /* Get the physical address of the buffer in memory */
        gem = drm_fb_cma_get_gem_obj(fb, 0);
 
        /* Set the line width */
        DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_CHAN_UI_LAYER_PITCH(channel, overlay),
+                    SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch_base, overlay),
                     fb->pitches[0]);
 
        DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(channel, overlay),
+                    SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch_base, overlay),
                     lower_32_bits(paddr));
 
        return 0;
 
 
 #include <drm/drm_plane.h>
 
-#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
-                       (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
-#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
-                       (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
-#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
-                       (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
-#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
-                       (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
-#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
-                       (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
-#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
-                       (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
-#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
-                       (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
-#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)      (0x2000 + 0x1000 * (ch) + 0x80)
-#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)      (0x2000 + 0x1000 * (ch) + 0x84)
-#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)       (0x2000 + 0x1000 * (ch) + 0x88)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(base, layer) \
+                       ((base) + 0x20 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(base, layer) \
+                       ((base) + 0x20 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(base, layer) \
+                       ((base) + 0x20 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(base, layer) \
+                       ((base) + 0x20 * (layer) + 0xc)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(base, layer) \
+                       ((base) + 0x20 * (layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(base, layer) \
+                       ((base) + 0x20 * (layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(base, layer) \
+                       ((base) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(base) \
+                       ((base) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(base) \
+                       ((base) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(base) \
+                       ((base) + 0x88)
 
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN              BIT(0)
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK GENMASK(2, 1)
 
  */
 
 #include "sun8i_ui_scaler.h"
+#include "sun8i_vi_scaler.h"
 
 static const u32 lan2coefftab16[240] = {
        0x00004000, 0x00033ffe, 0x00063efc, 0x000a3bfb,
        0x0b1c1603, 0x0d1c1502, 0x0e1d1401, 0x0f1d1301,
 };
 
+static u32 sun8i_ui_scaler_base(struct sun8i_mixer *mixer, int channel)
+{
+       int vi_num = mixer->cfg->vi_num;
+
+       return DE2_VI_SCALER_UNIT_BASE + DE2_VI_SCALER_UNIT_SIZE * vi_num +
+              DE2_UI_SCALER_UNIT_SIZE * (channel - vi_num);
+}
+
 static int sun8i_ui_scaler_coef_index(unsigned int step)
 {
        unsigned int scale, int_part, float_part;
 
 void sun8i_ui_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
 {
-       int vi_cnt = mixer->cfg->vi_num;
-       u32 val;
+       u32 val, base;
 
-       if (WARN_ON(layer < vi_cnt))
+       if (WARN_ON(layer < mixer->cfg->vi_num))
                return;
 
+       base = sun8i_ui_scaler_base(mixer, layer);
+
        if (enable)
                val = SUN8I_SCALER_GSU_CTRL_EN |
                      SUN8I_SCALER_GSU_CTRL_COEFF_RDY;
        else
                val = 0;
 
-       regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_GSU_CTRL(vi_cnt, layer - vi_cnt), val);
+       regmap_write(mixer->engine.regs, SUN8I_SCALER_GSU_CTRL(base), val);
 }
 
 void sun8i_ui_scaler_setup(struct sun8i_mixer *mixer, int layer,
                           u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
                           u32 hscale, u32 vscale, u32 hphase, u32 vphase)
 {
-       int vi_cnt = mixer->cfg->vi_num;
        u32 insize, outsize;
        int i, offset;
+       u32 base;
 
-       if (WARN_ON(layer < vi_cnt))
+       if (WARN_ON(layer < mixer->cfg->vi_num))
                return;
 
+       base = sun8i_ui_scaler_base(mixer, layer);
+
        hphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16;
        vphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16;
        hscale <<= SUN8I_UI_SCALER_SCALE_FRAC - 16;
        insize = SUN8I_UI_SCALER_SIZE(src_w, src_h);
        outsize = SUN8I_UI_SCALER_SIZE(dst_w, dst_h);
 
-       layer -= vi_cnt;
-
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_GSU_OUTSIZE(vi_cnt, layer), outsize);
+                    SUN8I_SCALER_GSU_OUTSIZE(base), outsize);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_GSU_INSIZE(vi_cnt, layer), insize);
+                    SUN8I_SCALER_GSU_INSIZE(base), insize);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_GSU_HSTEP(vi_cnt, layer), hscale);
+                    SUN8I_SCALER_GSU_HSTEP(base), hscale);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_GSU_VSTEP(vi_cnt, layer), vscale);
+                    SUN8I_SCALER_GSU_VSTEP(base), vscale);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_GSU_HPHASE(vi_cnt, layer), hphase);
+                    SUN8I_SCALER_GSU_HPHASE(base), hphase);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_GSU_VPHASE(vi_cnt, layer), vphase);
+                    SUN8I_SCALER_GSU_VPHASE(base), vphase);
        offset = sun8i_ui_scaler_coef_index(hscale) *
                        SUN8I_UI_SCALER_COEFF_COUNT;
        for (i = 0; i < SUN8I_UI_SCALER_COEFF_COUNT; i++)
                regmap_write(mixer->engine.regs,
-                            SUN8I_SCALER_GSU_HCOEFF(vi_cnt, layer, i),
+                            SUN8I_SCALER_GSU_HCOEFF(base, i),
                             lan2coefftab16[offset + i]);
 }
 
 
 #include "sun8i_mixer.h"
 
+#define DE2_UI_SCALER_UNIT_SIZE 0x10000
+
 /* this two macros assumes 16 fractional bits which is standard in DRM */
 #define SUN8I_UI_SCALER_SCALE_MIN              1
 #define SUN8I_UI_SCALER_SCALE_MAX              ((1UL << 20) - 1)
 #define SUN8I_UI_SCALER_COEFF_COUNT            16
 #define SUN8I_UI_SCALER_SIZE(w, h)             (((h) - 1) << 16 | ((w) - 1))
 
-#define SUN8I_SCALER_GSU_CTRL(vi_cnt, ui_idx) \
-       (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x0)
-#define SUN8I_SCALER_GSU_OUTSIZE(vi_cnt, ui_idx) \
-       (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x40)
-#define SUN8I_SCALER_GSU_INSIZE(vi_cnt, ui_idx) \
-       (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x80)
-#define SUN8I_SCALER_GSU_HSTEP(vi_cnt, ui_idx) \
-       (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x88)
-#define SUN8I_SCALER_GSU_VSTEP(vi_cnt, ui_idx) \
-       (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x8c)
-#define SUN8I_SCALER_GSU_HPHASE(vi_cnt, ui_idx) \
-       (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x90)
-#define SUN8I_SCALER_GSU_VPHASE(vi_cnt, ui_idx) \
-       (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x98)
-#define SUN8I_SCALER_GSU_HCOEFF(vi_cnt, ui_idx, index) \
-       (0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x200 + \
-       0x4 * (index))
+#define SUN8I_SCALER_GSU_CTRL(base)            ((base) + 0x0)
+#define SUN8I_SCALER_GSU_OUTSIZE(base)         ((base) + 0x40)
+#define SUN8I_SCALER_GSU_INSIZE(base)          ((base) + 0x80)
+#define SUN8I_SCALER_GSU_HSTEP(base)           ((base) + 0x88)
+#define SUN8I_SCALER_GSU_VSTEP(base)           ((base) + 0x8c)
+#define SUN8I_SCALER_GSU_HPHASE(base)          ((base) + 0x90)
+#define SUN8I_SCALER_GSU_VPHASE(base)          ((base) + 0x98)
+#define SUN8I_SCALER_GSU_HCOEFF(base, index)   ((base) + 0x200 + 0x4 * (index))
 
 #define SUN8I_SCALER_GSU_CTRL_EN               BIT(0)
 #define SUN8I_SCALER_GSU_CTRL_COEFF_RDY                BIT(4)
 
                                  int overlay, bool enable, unsigned int zpos,
                                  unsigned int old_zpos)
 {
-       u32 val;
+       u32 val, bld_base, ch_base;
+
+       bld_base = sun8i_blender_base(mixer);
+       ch_base = sun8i_channel_base(mixer, channel);
 
        DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n",
                         enable ? "En" : "Dis", channel, overlay);
                val = 0;
 
        regmap_update_bits(mixer->engine.regs,
-                          SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
+                          SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
                           SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
 
        if (!enable || zpos != old_zpos) {
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_PIPE_CTL,
+                                  SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
                                   SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
                                   0);
 
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_ROUTE,
+                                  SUN8I_MIXER_BLEND_ROUTE(bld_base),
                                   SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
                                   0);
        }
                val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
 
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_PIPE_CTL, val, val);
+                                  SUN8I_MIXER_BLEND_PIPE_CTL(bld_base),
+                                  val, val);
 
                val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
 
                regmap_update_bits(mixer->engine.regs,
-                                  SUN8I_MIXER_BLEND_ROUTE,
+                                  SUN8I_MIXER_BLEND_ROUTE(bld_base),
                                   SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
                                   val);
        }
        struct drm_plane_state *state = plane->state;
        const struct drm_format_info *format = state->fb->format;
        u32 src_w, src_h, dst_w, dst_h;
+       u32 bld_base, ch_base;
        u32 outsize, insize;
        u32 hphase, vphase;
        bool subsampled;
        DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
                         channel, overlay);
 
+       bld_base = sun8i_blender_base(mixer);
+       ch_base = sun8i_channel_base(mixer, channel);
+
        src_w = drm_rect_width(&state->src) >> 16;
        src_h = drm_rect_height(&state->src) >> 16;
        dst_w = drm_rect_width(&state->dst);
                         (state->src.y1 >> 16) & ~(format->vsub - 1));
        DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_CHAN_VI_LAYER_SIZE(channel, overlay),
+                    SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch_base, overlay),
                     insize);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel),
+                    SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch_base),
                     insize);
 
        /*
                         state->dst.x1, state->dst.y1);
        DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_BLEND_ATTR_COORD(zpos),
+                    SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos),
                     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
        regmap_write(mixer->engine.regs,
-                    SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos),
+                    SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos),
                     outsize);
 
        return 0;
 {
        struct drm_plane_state *state = plane->state;
        const struct de2_fmt_info *fmt_info;
-       u32 val;
+       u32 val, ch_base;
+
+       ch_base = sun8i_channel_base(mixer, channel);
 
        fmt_info = sun8i_mixer_format_info(state->fb->format->format);
        if (!fmt_info) {
 
        val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET;
        regmap_update_bits(mixer->engine.regs,
-                          SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
+                          SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
                           SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val);
 
        if (fmt_info->csc != SUN8I_CSC_MODE_OFF) {
                val = 0;
 
        regmap_update_bits(mixer->engine.regs,
-                          SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
+                          SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay),
                           SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE, val);
 
        return 0;
        struct drm_gem_cma_object *gem;
        u32 dx, dy, src_x, src_y;
        dma_addr_t paddr;
+       u32 ch_base;
        int i;
 
+       ch_base = sun8i_channel_base(mixer, channel);
+
        /* Adjust x and y to be dividable by subsampling factor */
        src_x = (state->src.x1 >> 16) & ~(format->hsub - 1);
        src_y = (state->src.y1 >> 16) & ~(format->vsub - 1);
                DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n",
                                 i + 1, fb->pitches[i]);
                regmap_write(mixer->engine.regs,
-                            SUN8I_MIXER_CHAN_VI_LAYER_PITCH(channel,
+                            SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch_base,
                                                             overlay, i),
-              fb->pitches[i]);
+                            fb->pitches[i]);
 
                DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n",
                                 i + 1, &paddr);
 
                regmap_write(mixer->engine.regs,
-                            SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(channel,
+                            SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch_base,
                                                                 overlay, i),
-              lower_32_bits(paddr));
+                            lower_32_bits(paddr));
        }
 
        return 0;
 
 
 #include <drm/drm_plane.h>
 
-#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch, layer) \
-               (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x0)
-#define SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch, layer) \
-               (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x4)
-#define SUN8I_MIXER_CHAN_VI_LAYER_COORD(ch, layer) \
-               (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x8)
-#define SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch, layer, plane) \
-               (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0xc + 4 * (plane))
-#define SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch, layer, plane) \
-               (0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x18 + 4 * (plane))
-#define SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch)       (0x2000 + 0x1000 * (ch) + 0xe8)
+#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR(base, layer) \
+               ((base) + 0x30 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_VI_LAYER_SIZE(base, layer) \
+               ((base) + 0x30 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_VI_LAYER_COORD(base, layer) \
+               ((base) + 0x30 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_VI_LAYER_PITCH(base, layer, plane) \
+               ((base) + 0x30 * (layer) + 0xc + 4 * (plane))
+#define SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(base, layer, plane) \
+               ((base) + 0x30 * (layer) + 0x18 + 4 * (plane))
+#define SUN8I_MIXER_CHAN_VI_OVL_SIZE(base) \
+               ((base) + 0xe8)
 
 #define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN              BIT(0)
 /* RGB mode should be set for RGB formats and cleared for YCbCr */
 
        0x1012110d, 0x1012110d, 0x1013110c, 0x1013110c,
 };
 
+static u32 sun8i_vi_scaler_base(struct sun8i_mixer *mixer, int channel)
+{
+       return DE2_VI_SCALER_UNIT_BASE + DE2_VI_SCALER_UNIT_SIZE * channel;
+}
+
 static int sun8i_vi_scaler_coef_index(unsigned int step)
 {
        unsigned int scale, int_part, float_part;
        }
 }
 
-static void sun8i_vi_scaler_set_coeff(struct regmap *map, int layer,
+static void sun8i_vi_scaler_set_coeff(struct regmap *map, u32 base,
                                      u32 hstep, u32 vstep,
                                      const struct drm_format_info *format)
 {
        offset = sun8i_vi_scaler_coef_index(hstep) *
                        SUN8I_VI_SCALER_COEFF_COUNT;
        for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) {
-               regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF0(layer, i),
+               regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF0(base, i),
                             lan3coefftab32_left[offset + i]);
-               regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF1(layer, i),
+               regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF1(base, i),
                             lan3coefftab32_right[offset + i]);
-               regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF0(layer, i),
+               regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF0(base, i),
                             ch_left[offset + i]);
-               regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF1(layer, i),
+               regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF1(base, i),
                             ch_right[offset + i]);
        }
 
        offset = sun8i_vi_scaler_coef_index(hstep) *
                        SUN8I_VI_SCALER_COEFF_COUNT;
        for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) {
-               regmap_write(map, SUN8I_SCALER_VSU_YVCOEFF(layer, i),
+               regmap_write(map, SUN8I_SCALER_VSU_YVCOEFF(base, i),
                             lan2coefftab32[offset + i]);
-               regmap_write(map, SUN8I_SCALER_VSU_CVCOEFF(layer, i),
+               regmap_write(map, SUN8I_SCALER_VSU_CVCOEFF(base, i),
                             cy[offset + i]);
        }
 }
 
 void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
 {
-       u32 val;
+       u32 val, base;
+
+       base = sun8i_vi_scaler_base(mixer, layer);
 
        if (enable)
                val = SUN8I_SCALER_VSU_CTRL_EN |
        else
                val = 0;
 
-       regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(layer), val);
+       regmap_write(mixer->engine.regs,
+                    SUN8I_SCALER_VSU_CTRL(base), val);
 }
 
 void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
 {
        u32 chphase, cvphase;
        u32 insize, outsize;
+       u32 base;
+
+       base = sun8i_vi_scaler_base(mixer, layer);
 
        hphase <<= SUN8I_VI_SCALER_PHASE_FRAC - 16;
        vphase <<= SUN8I_VI_SCALER_PHASE_FRAC - 16;
        }
 
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_OUTSIZE(layer), outsize);
+                    SUN8I_SCALER_VSU_OUTSIZE(base), outsize);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_YINSIZE(layer), insize);
+                    SUN8I_SCALER_VSU_YINSIZE(base), insize);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_YHSTEP(layer), hscale);
+                    SUN8I_SCALER_VSU_YHSTEP(base), hscale);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_YVSTEP(layer), vscale);
+                    SUN8I_SCALER_VSU_YVSTEP(base), vscale);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_YHPHASE(layer), hphase);
+                    SUN8I_SCALER_VSU_YHPHASE(base), hphase);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_YVPHASE(layer), vphase);
+                    SUN8I_SCALER_VSU_YVPHASE(base), vphase);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_CINSIZE(layer),
+                    SUN8I_SCALER_VSU_CINSIZE(base),
                     SUN8I_VI_SCALER_SIZE(src_w / format->hsub,
                                          src_h / format->vsub));
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_CHSTEP(layer),
+                    SUN8I_SCALER_VSU_CHSTEP(base),
                     hscale / format->hsub);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_CVSTEP(layer),
+                    SUN8I_SCALER_VSU_CVSTEP(base),
                     vscale / format->vsub);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_CHPHASE(layer), chphase);
+                    SUN8I_SCALER_VSU_CHPHASE(base), chphase);
        regmap_write(mixer->engine.regs,
-                    SUN8I_SCALER_VSU_CVPHASE(layer), cvphase);
-       sun8i_vi_scaler_set_coeff(mixer->engine.regs, layer,
+                    SUN8I_SCALER_VSU_CVPHASE(base), cvphase);
+       sun8i_vi_scaler_set_coeff(mixer->engine.regs, base,
                                  hscale, vscale, format);
 }
 
 #include <drm/drm_fourcc.h>
 #include "sun8i_mixer.h"
 
+#define DE2_VI_SCALER_UNIT_BASE 0x20000
+#define DE2_VI_SCALER_UNIT_SIZE 0x20000
+
 /* this two macros assumes 16 fractional bits which is standard in DRM */
 #define SUN8I_VI_SCALER_SCALE_MIN              1
 #define SUN8I_VI_SCALER_SCALE_MAX              ((1UL << 20) - 1)
 #define SUN8I_VI_SCALER_COEFF_COUNT            32
 #define SUN8I_VI_SCALER_SIZE(w, h)             (((h) - 1) << 16 | ((w) - 1))
 
-#define SUN8I_SCALER_VSU_CTRL(ch)      (0x20000 + 0x20000 * (ch) + 0x0)
-#define SUN8I_SCALER_VSU_OUTSIZE(ch)   (0x20000 + 0x20000 * (ch) + 0x40)
-#define SUN8I_SCALER_VSU_YINSIZE(ch)   (0x20000 + 0x20000 * (ch) + 0x80)
-#define SUN8I_SCALER_VSU_YHSTEP(ch)    (0x20000 + 0x20000 * (ch) + 0x88)
-#define SUN8I_SCALER_VSU_YVSTEP(ch)    (0x20000 + 0x20000 * (ch) + 0x8c)
-#define SUN8I_SCALER_VSU_YHPHASE(ch)   (0x20000 + 0x20000 * (ch) + 0x90)
-#define SUN8I_SCALER_VSU_YVPHASE(ch)   (0x20000 + 0x20000 * (ch) + 0x98)
-#define SUN8I_SCALER_VSU_CINSIZE(ch)   (0x20000 + 0x20000 * (ch) + 0xc0)
-#define SUN8I_SCALER_VSU_CHSTEP(ch)    (0x20000 + 0x20000 * (ch) + 0xc8)
-#define SUN8I_SCALER_VSU_CVSTEP(ch)    (0x20000 + 0x20000 * (ch) + 0xcc)
-#define SUN8I_SCALER_VSU_CHPHASE(ch)   (0x20000 + 0x20000 * (ch) + 0xd0)
-#define SUN8I_SCALER_VSU_CVPHASE(ch)   (0x20000 + 0x20000 * (ch) + 0xd8)
-#define SUN8I_SCALER_VSU_YHCOEFF0(ch, i) \
-       (0x20000 + 0x20000 * (ch) + 0x200 + 0x4 * (i))
-#define SUN8I_SCALER_VSU_YHCOEFF1(ch, i) \
-       (0x20000 + 0x20000 * (ch) + 0x300 + 0x4 * (i))
-#define SUN8I_SCALER_VSU_YVCOEFF(ch, i) \
-       (0x20000 + 0x20000 * (ch) + 0x400 + 0x4 * (i))
-#define SUN8I_SCALER_VSU_CHCOEFF0(ch, i) \
-       (0x20000 + 0x20000 * (ch) + 0x600 + 0x4 * (i))
-#define SUN8I_SCALER_VSU_CHCOEFF1(ch, i) \
-       (0x20000 + 0x20000 * (ch) + 0x700 + 0x4 * (i))
-#define SUN8I_SCALER_VSU_CVCOEFF(ch, i) \
-       (0x20000 + 0x20000 * (ch) + 0x800 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_CTRL(base)            ((base) + 0x0)
+#define SUN8I_SCALER_VSU_OUTSIZE(base)         ((base) + 0x40)
+#define SUN8I_SCALER_VSU_YINSIZE(base)         ((base) + 0x80)
+#define SUN8I_SCALER_VSU_YHSTEP(base)          ((base) + 0x88)
+#define SUN8I_SCALER_VSU_YVSTEP(base)          ((base) + 0x8c)
+#define SUN8I_SCALER_VSU_YHPHASE(base)         ((base) + 0x90)
+#define SUN8I_SCALER_VSU_YVPHASE(base)         ((base) + 0x98)
+#define SUN8I_SCALER_VSU_CINSIZE(base)         ((base) + 0xc0)
+#define SUN8I_SCALER_VSU_CHSTEP(base)          ((base) + 0xc8)
+#define SUN8I_SCALER_VSU_CVSTEP(base)          ((base) + 0xcc)
+#define SUN8I_SCALER_VSU_CHPHASE(base)         ((base) + 0xd0)
+#define SUN8I_SCALER_VSU_CVPHASE(base)         ((base) + 0xd8)
+#define SUN8I_SCALER_VSU_YHCOEFF0(base, i)     ((base) + 0x200 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_YHCOEFF1(base, i)     ((base) + 0x300 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_YVCOEFF(base, i)      ((base) + 0x400 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_CHCOEFF0(base, i)     ((base) + 0x600 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_CHCOEFF1(base, i)     ((base) + 0x700 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_CVCOEFF(base, i)      ((base) + 0x800 + 0x4 * (i))
 
 #define SUN8I_SCALER_VSU_CTRL_EN               BIT(0)
 #define SUN8I_SCALER_VSU_CTRL_COEFF_RDY                BIT(4)