};
 
 static const struct malidp_layer malidp500_layers[] = {
-       { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE },
-       { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE },
-       { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE },
+       { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
+       { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE },
+       { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE },
 };
 
 static const struct malidp_layer malidp550_layers[] = {
-       { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE },
-       { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE },
-       { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE },
-       { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE },
+       { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
+       { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE },
+       { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0 },
+       { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, 0 },
 };
 
 #define MALIDP_DE_DEFAULT_PREFETCH_START       5
                .set_config_valid = malidp500_set_config_valid,
                .modeset = malidp500_modeset,
                .rotmem_required = malidp500_rotmem_required,
+               .features = MALIDP_DEVICE_LV_HAS_3_STRIDES,
        },
        [MALIDP_550] = {
                .map = {
                .set_config_valid = malidp550_set_config_valid,
                .modeset = malidp550_modeset,
                .rotmem_required = malidp550_rotmem_required,
+               .features = 0,
        },
        [MALIDP_650] = {
                .map = {
                .set_config_valid = malidp550_set_config_valid,
                .modeset = malidp550_modeset,
                .rotmem_required = malidp550_rotmem_required,
+               .features = 0,
        },
 };
 
 
        u16 id;                 /* layer ID */
        u16 base;               /* address offset for the register bank */
        u16 ptr;                /* address offset for the pointer register */
+       u16 stride_offset;      /* Offset to the first stride register. */
 };
 
 /* regmap features */
        const u8 bus_align_bytes;
 };
 
+/* device features */
+/* Unlike DP550/650, DP500 has 3 stride registers in its video layer. */
+#define MALIDP_DEVICE_LV_HAS_3_STRIDES BIT(0)
+
 struct malidp_hw_device {
        const struct malidp_hw_regmap map;
        void __iomem *regs;
 
 #define   LAYER_V_VAL(x)               (((x) & 0x1fff) << 16)
 #define MALIDP_LAYER_COMP_SIZE         0x010
 #define MALIDP_LAYER_OFFSET            0x014
-#define MALIDP_LAYER_STRIDE            0x018
 
 /*
  * This 4-entry look-up-table is used to determine the full 8-bit alpha value
            (state->crtc_h < mp->hwdev->min_line_size))
                return -EINVAL;
 
+       /*
+        * DP550/650 video layers can accept 3 plane formats only if
+        * fb->pitches[1] == fb->pitches[2] since they don't have a
+        * third plane stride register.
+        */
+       if (ms->n_planes == 3 &&
+           !(mp->hwdev->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) &&
+           (state->fb->pitches[1] != state->fb->pitches[2]))
+               return -EINVAL;
+
        /* packed RGB888 / BGR888 can't be rotated or flipped */
        if (state->rotation != DRM_ROTATE_0 &&
            (fb->format->format == DRM_FORMAT_RGB888 ||
        return 0;
 }
 
+static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
+                                       int num_planes, unsigned int pitches[3])
+{
+       int i;
+       int num_strides = num_planes;
+
+       if (!mp->layer->stride_offset)
+               return;
+
+       if (num_planes == 3)
+               num_strides = (mp->hwdev->features &
+                              MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2;
+
+       for (i = 0; i < num_strides; ++i)
+               malidp_hw_write(mp->hwdev, pitches[i],
+                               mp->layer->base +
+                               mp->layer->stride_offset + i * 4);
+}
+
 static void malidp_de_plane_update(struct drm_plane *plane,
                                   struct drm_plane_state *old_state)
 {
                obj->paddr += plane->state->fb->offsets[i];
                malidp_hw_write(mp->hwdev, lower_32_bits(obj->paddr), ptr);
                malidp_hw_write(mp->hwdev, upper_32_bits(obj->paddr), ptr + 4);
-               malidp_hw_write(mp->hwdev, plane->state->fb->pitches[i],
-                               mp->layer->base + MALIDP_LAYER_STRIDE);
        }
+       malidp_de_set_plane_pitches(mp, ms->n_planes,
+                                   plane->state->fb->pitches);
 
        malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
                        mp->layer->base + MALIDP_LAYER_SIZE);
 
 #define MALIDP_DE_SYNC_WIDTH           0x8
 #define MALIDP_DE_HV_ACTIVE            0xc
 
+/* Stride register offsets relative to Lx_BASE */
+#define MALIDP_DE_LG_STRIDE            0x18
+#define MALIDP_DE_LV_STRIDE0           0x18
+
 /* macros to set values into registers */
 #define MALIDP_DE_H_FRONTPORCH(x)      (((x) & 0xfff) << 0)
 #define MALIDP_DE_H_BACKPORCH(x)       (((x) & 0x3ff) << 16)