drm: mali-dp: fix stride setting for multi-plane formats
authorMihail Atanassov <mihail.atanassov@arm.com>
Mon, 23 Jan 2017 15:24:35 +0000 (15:24 +0000)
committerLiviu Dudau <Liviu.Dudau@arm.com>
Thu, 26 Jan 2017 15:46:19 +0000 (15:46 +0000)
Hardware has multiple (2 or 3, depending on model) stride
registers per layer; add a function that correctly takes that
into account. On hardware that only has 2 stride registers,
ensure that 3-plane (YUV) content has identical strides
for both chroma planes.

Signed-off-by: Mihail Atanassov <mihail.atanassov@arm.com>
[Removed smart layer stride setup, comment and commit message clarifications]
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
drivers/gpu/drm/arm/malidp_hw.c
drivers/gpu/drm/arm/malidp_hw.h
drivers/gpu/drm/arm/malidp_planes.c
drivers/gpu/drm/arm/malidp_regs.h

index 9ec6d6904f5e59dbf9c9617a03c464d3c547077b..488aedf5b58d54e7997b2339c75b7a90f30dcfc1 100644 (file)
@@ -74,16 +74,16 @@ 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 },
-       { 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
@@ -447,6 +447,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
                .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 = {
@@ -480,6 +481,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
                .set_config_valid = malidp550_set_config_valid,
                .modeset = malidp550_modeset,
                .rotmem_required = malidp550_rotmem_required,
+               .features = 0,
        },
        [MALIDP_650] = {
                .map = {
@@ -514,6 +516,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
                .set_config_valid = malidp550_set_config_valid,
                .modeset = malidp550_modeset,
                .rotmem_required = malidp550_rotmem_required,
+               .features = 0,
        },
 };
 
index 4f8c884d1960e2f10a387b22f3feded4599cf260..00974b59407df59915c5751d5845228d040f91b7 100644 (file)
@@ -58,6 +58,7 @@ 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. */
 };
 
 /* regmap features */
@@ -93,6 +94,10 @@ struct malidp_hw_regmap {
        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;
index 837874e793342e881e82605fb0802c30b8ac2384..414aada10fe5e7d43392aa835b4c01aba594bcb7 100644 (file)
@@ -37,7 +37,6 @@
 #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
@@ -138,6 +137,16 @@ static int malidp_de_plane_check(struct drm_plane *plane,
            (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 ||
@@ -170,6 +179,25 @@ static int malidp_de_plane_check(struct drm_plane *plane,
        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)
 {
@@ -200,9 +228,9 @@ static void malidp_de_plane_update(struct drm_plane *plane,
                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);
index e0651d28c485a45e9f006599c81a9cd1e623d84a..aff6d4a84e998c6cc1d01e3067d0f52712daa145 100644 (file)
 #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)