The IPU IDMAC handles multiplanar formats using a base address and relative
offsets for the secondary planes. Since those offsets must be positive
and not too large and can't be changed when doing a page flip while scanout
is active, just enforce the same physical base address on all planes.

Signed-off-by: Philipp Zabel <p.zabel at pengutronix.de>
---
 drivers/gpu/drm/imx/ipuv3-plane.c | 39 +++++++++++++++++++++++++++++++--------
 1 file changed, 31 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c 
b/drivers/gpu/drm/imx/ipuv3-plane.c
index 878a643..435eec1 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -62,22 +62,45 @@ static inline int calc_bandwidth(int width, int height, 
unsigned int vref)
 int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
                       int x, int y)
 {
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_cma_object *cma_obj[3];
        unsigned long eba;
-       int active;
+       int active, i;

-       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       if (!cma_obj) {
-               DRM_DEBUG_KMS("entry is null.\n");
-               return -EFAULT;
+       for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
+               cma_obj[i] = drm_fb_cma_get_gem_obj(fb, i);
+               if (!cma_obj[i]) {
+                       DRM_DEBUG_KMS("plane %d entry is null.\n", i);
+                       return -EFAULT;
+               }
        }

        dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
-               &cma_obj->paddr, x, y);
+               &cma_obj[0]->paddr, x, y);

-       eba = cma_obj->paddr + fb->offsets[0] +
+       eba = cma_obj[0]->paddr + fb->offsets[0] +
              fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;

+       switch (fb->pixel_format) {
+       case DRM_FORMAT_YUV420:
+       case DRM_FORMAT_YVU420:
+               /*
+                * Multiplanar formats have to meet the following restrictions:
+                * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
+                * - EBA, UBO and VBO are a multiple of 8
+                * - UBO and VBO are unsigned and not larger than 0xfffff8
+                * - Only EBA may be changed while scanout is active
+                *
+                * For now, enforce the same physical base address for all
+                * planes.
+                */
+               if (cma_obj[0]->paddr != cma_obj[1]->paddr ||
+                   cma_obj[0]->paddr != cma_obj[2]->paddr) {
+                       DRM_DEBUG_KMS("plane base addresses differ.\n");
+                       return -EINVAL;
+               }
+               break;
+       }
+
        if (ipu_plane->enabled) {
                active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
                ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
-- 
2.5.0

Reply via email to