Mali-DP 500 supports rotations for both compressed/uncompressed buffers
for all the layers.
Mali-DP 550 supports rotations for both compressed/uncompressed buffers for
VIDEO and GRAPHICS layers only. The SMART layer does not support any
rotation.
Mali-DP 650 supports rotations for both compressed/uncompressed buffers for
VIDEO layers and compressed buffers only for GRAPHICS layer. SMART layer
behaves similar to that of Malidp-550.

Signed-off-by: Ayan Kumar halder <[email protected]>
Reviewed-by: Brian Starkey <[email protected]>
---
 drivers/gpu/drm/arm/malidp_crtc.c   | 31 ++++++++++++++----------
 drivers/gpu/drm/arm/malidp_hw.c     | 48 ++++++++++++++++++++++++++-----------
 drivers/gpu/drm/arm/malidp_hw.h     | 10 +++++++-
 drivers/gpu/drm/arm/malidp_planes.c | 24 +++++++++++++------
 4 files changed, 79 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/arm/malidp_crtc.c 
b/drivers/gpu/drm/arm/malidp_crtc.c
index fcc62bc..21c5d05 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -348,19 +348,20 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
 
        /*
         * check if there is enough rotation memory available for planes
-        * that need 90° and 270° rotation. Each plane has set its required
-        * memory size in the ->plane_check() callback, here we only make
-        * sure that the sums are less that the total usable memory.
+        * that need 90° and 270° rotion or planes that are compressed.
+        * Each plane has set its required memory size in the ->plane_check()
+        * callback, here we only make sure that the sums are less that the
+        * total usable memory.
         *
         * The rotation memory allocation algorithm (for each plane):
-        *  a. If no more rotated planes exist, all remaining rotate
-        *     memory in the bank is available for use by the plane.
-        *  b. If other rotated planes exist, and plane's layer ID is
-        *     DE_VIDEO1, it can use all the memory from first bank if
-        *     secondary rotation memory bank is available, otherwise it can
+        *  a. If no more rotated or compressed planes exist, all remaining
+        *     rotate memory in the bank is available for use by the plane.
+        *  b. If other rotated or compressed planes exist, and plane's
+        *     layer ID is DE_VIDEO1, it can use all the memory from first bank
+        *     if secondary rotation memory bank is available, otherwise it can
         *     use up to half the bank's memory.
-        *  c. If other rotated planes exist, and plane's layer ID is not
-        *     DE_VIDEO1, it can use half of the available memory
+        *  c. If other rotated or compressed planes exist, and plane's layer ID
+        *     is not DE_VIDEO1, it can use half of the available memory.
         *
         * Note: this algorithm assumes that the order in which the planes are
         * checked always has DE_VIDEO1 plane first in the list if it is
@@ -368,11 +369,15 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
         * place, under current DRM version things work, but if ever the order
         * in which drm_atomic_crtc_state_for_each_plane() iterates over planes
         * changes, we need to pre-sort the planes before validation.
+        *
         */
 
        /* first count the number of rotated planes */
        drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
-               if (pstate->rotation & MALIDP_ROTATED_MASK)
+               struct malidp_plane_state *ms = to_malidp_plane_state(pstate);
+               struct drm_framebuffer *fb = ms->base.fb;
+
+               if ((pstate->rotation & MALIDP_ROTATED_MASK) || fb->modifier)
                        rotated_planes++;
        }
 
@@ -388,8 +393,10 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
        drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
                struct malidp_plane *mp = to_malidp_plane(plane);
                struct malidp_plane_state *ms = to_malidp_plane_state(pstate);
+               struct drm_framebuffer *fb = ms->base.fb;
+
+               if ((pstate->rotation & MALIDP_ROTATED_MASK) || fb->modifier) {
 
-               if (pstate->rotation & MALIDP_ROTATED_MASK) {
                        /* process current plane */
                        rotated_planes--;
 
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index d789b46..4dbf39f 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -75,16 +75,34 @@ static const struct malidp_format_id malidp550_de_formats[] 
= {
 };
 
 static const struct malidp_layer malidp500_layers[] = {
-       { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, 
MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB },
-       { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, 
MALIDP_DE_LG_STRIDE, 0 },
-       { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, 
MALIDP_DE_LG_STRIDE, 0 },
+       { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
+               MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, ROTATE_ANY },
+       { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
+               MALIDP_DE_LG_STRIDE, 0, ROTATE_ANY },
+       { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
+               MALIDP_DE_LG_STRIDE, 0, ROTATE_ANY },
 };
 
 static const struct malidp_layer malidp550_layers[] = {
-       { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, 
MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
-       { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, 
MALIDP_DE_LG_STRIDE, 0 },
-       { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, 
MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
-       { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, 
MALIDP550_DE_LS_R1_STRIDE, 0 },
+       { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
+               MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, ROTATE_ANY },
+       { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
+               MALIDP_DE_LG_STRIDE, 0, ROTATE_ANY },
+       { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
+               MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, ROTATE_ANY },
+       { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
+               MALIDP550_DE_LS_R1_STRIDE, 0, ROTATE_NONE },
+};
+
+static const struct malidp_layer malidp650_layers[] = {
+       { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
+               MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, ROTATE_ANY },
+       { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
+               MALIDP_DE_LG_STRIDE, 0, ROTATE_COMPRESSED },
+       { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
+               MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, ROTATE_ANY },
+       { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
+               MALIDP550_DE_LS_R1_STRIDE, 0, ROTATE_NONE },
 };
 
 #define SE_N_SCALING_COEFFS    96
@@ -272,10 +290,11 @@ static void malidp500_modeset(struct malidp_hw_device 
*hwdev, struct videomode *
                malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, 
MALIDP_DE_DISPLAY_FUNC);
 }
 
-static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, 
u16 h, u32 fmt)
+static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
+                                    u16 h, u32 fmt, bool has_modifier)
 {
-       /* RGB888 or BGR888 can't be rotated */
-       if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
+       /* raw RGB888 or BGR888 can't be rotated */
+       if ((fmt == DRM_FORMAT_RGB888 || fmt == DRM_FORMAT_BGR888) && 
!has_modifier)
                return -EINVAL;
 
        /*
@@ -496,12 +515,13 @@ static void malidp550_modeset(struct malidp_hw_device 
*hwdev, struct videomode *
                malidp_hw_clearbits(hwdev, MALIDP_DISP_FUNC_ILACED, 
MALIDP_DE_DISPLAY_FUNC);
 }
 
-static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, 
u16 h, u32 fmt)
+static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w,
+                                    u16 h, u32 fmt, bool has_modifier)
 {
        u32 bytes_per_col;
 
        /* raw RGB888 or BGR888 can't be rotated */
-       if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
+       if ((fmt == DRM_FORMAT_RGB888 || fmt == DRM_FORMAT_BGR888) && 
!has_modifier)
                return -EINVAL;
 
        switch (fmt) {
@@ -700,8 +720,8 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
                        .dc_base = MALIDP550_DC_BASE,
                        .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
                        .features = MALIDP_REGMAP_HAS_CLEARIRQ,
-                       .n_layers = ARRAY_SIZE(malidp550_layers),
-                       .layers = malidp550_layers,
+                       .n_layers = ARRAY_SIZE(malidp650_layers),
+                       .layers = malidp650_layers,
                        .de_irq_map = {
                                .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
                                            MALIDP650_DE_IRQ_DRIFT |
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index b5dd6c7..41f4521 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -54,12 +54,19 @@ struct malidp_irq_map {
        u32 vsync_irq;          /* IRQ bit used for signaling during VSYNC */
 };
 
+enum rotation_features {
+       ROTATE_ANY,             /* supports rotation on any buffers */
+       ROTATE_COMPRESSED,      /* supports rotation only on compressed buffers 
*/
+       ROTATE_NONE,        /* does not support rotation at all */
+};
+
 struct malidp_layer {
        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. */
        s16 yuv2rgb_offset;     /* offset to the YUV->RGB matrix entries */
+       enum rotation_features rot;    /* type of rotation supported */
 };
 
 enum malidp_scaling_coeff_set {
@@ -168,7 +175,8 @@ struct malidp_hw {
         * Calculate the required rotation memory given the active area
         * and the buffer format.
         */
-       int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h, 
u32 fmt);
+       int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h,
+                              u32 fmt, bool has_modifier);
 
        int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev,
                                     struct malidp_se_config *se_config,
diff --git a/drivers/gpu/drm/arm/malidp_planes.c 
b/drivers/gpu/drm/arm/malidp_planes.c
index 7a44897..377382e 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -197,12 +197,19 @@ static int malidp_de_plane_check(struct drm_plane *plane,
 
        ms->n_planes = fb->format->num_planes;
        for (i = 0; i < ms->n_planes; i++) {
+               struct drm_gem_cma_object *obj;
+
                u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated);
                if (fb->pitches[i] & (alignment - 1)) {
                        DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
                                      fb->pitches[i], i);
                        return -EINVAL;
                }
+
+               obj = drm_fb_cma_get_gem_obj(fb, i);
+
+               if (WARN_ON(!obj))
+                       return -EINVAL;
        }
 
        if ((state->crtc_w > mp->hwdev->max_line_size) ||
@@ -225,19 +232,22 @@ static int malidp_de_plane_check(struct drm_plane *plane,
        if (ret)
                return ret;
 
-       /* packed RGB888 / BGR888 can't be rotated or flipped */
-       if (state->rotation != DRM_MODE_ROTATE_0 &&
-           (fb->format->format == DRM_FORMAT_RGB888 ||
-            fb->format->format == DRM_FORMAT_BGR888))
-               return -EINVAL;
+       /* validate the rotation constraints for each layer */
+       if (state->rotation != DRM_MODE_ROTATE_0) {
+               if (mp->layer->rot == ROTATE_NONE)
+                       return -EINVAL;
+               else if ((mp->layer->rot == ROTATE_COMPRESSED) && 
(!fb->modifier))
+                       return -EINVAL;
+       }
 
        ms->rotmem_size = 0;
-       if (state->rotation & MALIDP_ROTATED_MASK) {
+       if (state->rotation != DRM_MODE_ROTATE_0 || fb->modifier) {
                int val;
 
                val = mp->hwdev->hw->rotmem_required(mp->hwdev, state->crtc_h,
                                                     state->crtc_w,
-                                                    fb->format->format);
+                                                    fb->format->format,
+                                                    !!(fb->modifier));
                if (val < 0)
                        return val;
 
-- 
2.7.4

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to