MLK-22649 drm/imx: dpu: plane: Add color properties support
authorLiu Ying <victor.liu@nxp.com>
Fri, 20 Sep 2019 05:12:14 +0000 (13:12 +0800)
committerLiu Ying <victor.liu@nxp.com>
Sat, 21 Sep 2019 08:09:38 +0000 (16:09 +0800)
As DPU fetchunits support ITU601(limited range)/ITU601_FR(full range)
and ITU709(limited range) YUV to RGB color space conversions, we may
add color encoding and color range properties support for planes.
Considering software backward compatibility, the default color encoding
is set to ITU601 with full color range.

Signed-off-by: Liu Ying <victor.liu@nxp.com>
(cherry picked from commit f491e24e65cb360fb0b3ce56f74d04fd80da77ab)

drivers/gpu/drm/imx/dpu/dpu-plane.c
drivers/gpu/imx/dpu/dpu-fetchdecode.c
drivers/gpu/imx/dpu/dpu-fetcheco.c
drivers/gpu/imx/dpu/dpu-fetchlayer.c
drivers/gpu/imx/dpu/dpu-fetchwarp.c
include/video/dpu.h

index 18e97f1..bd1843d 100644 (file)
@@ -16,6 +16,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
+#include <drm/drm_color_mgmt.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
@@ -85,6 +86,8 @@ static void dpu_plane_reset(struct drm_plane *plane)
        __drm_atomic_helper_plane_reset(plane, &state->base);
 
        plane->state->zpos = dpu_plane_get_default_zpos(plane->type);
+       plane->state->color_encoding = DRM_COLOR_YCBCR_BT601;
+       plane->state->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
 }
 
 static struct drm_plane_state *
@@ -220,6 +223,12 @@ drm_plane_state_to_uvbaseaddr(struct drm_plane_state *state, bool aux_source)
               drm_format_plane_cpp(fb->format->format, 1) * x;
 }
 
+static inline bool dpu_plane_fb_format_is_yuv(u32 fmt)
+{
+       return fmt == DRM_FORMAT_YUYV || fmt == DRM_FORMAT_UYVY ||
+              fmt == DRM_FORMAT_NV12 || fmt == DRM_FORMAT_NV21;
+}
+
 static int dpu_plane_atomic_check(struct drm_plane *plane,
                                  struct drm_plane_state *state)
 {
@@ -340,6 +349,12 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
                break;
        }
 
+       /* do not support BT709 full range */
+       if (dpu_plane_fb_format_is_yuv(fb->format->format) &&
+           state->color_encoding == DRM_COLOR_YCBCR_BT709 &&
+           state->color_range == DRM_COLOR_YCBCR_FULL_RANGE)
+               return -EINVAL;
+
 again:
        fu = source_to_fu(res,
                check_aux_source ? dpstate->aux_source : dpstate->source);
@@ -657,7 +672,8 @@ again:
        fu->ops->set_src_buf_dimensions(fu, src_w, src_h, 0, fb_is_interlaced);
        fu->ops->set_pixel_blend_mode(fu, state->pixel_blend_mode,
                                        state->alpha, fb->format->format);
-       fu->ops->set_fmt(fu, fb->format->format, fb_is_interlaced);
+       fu->ops->set_fmt(fu, fb->format->format, state->color_encoding,
+                                       state->color_range, fb_is_interlaced);
        fu->ops->enable_src_buf(fu);
        fu->ops->set_framedimensions(fu, src_w, src_h, fb_is_interlaced);
        fu->ops->set_baseaddress(fu, src_w, src_x, src_y, mt_w, mt_h, bpp,
@@ -688,7 +704,8 @@ again:
                fe->ops->set_src_stride(fe, src_w, src_x, mt_w, bpp,
                                        fb->pitches[1],
                                        uv_baseaddr, use_prefetch);
-               fe->ops->set_fmt(fe, fb->format->format, fb_is_interlaced);
+               fe->ops->set_fmt(fe, fb->format->format, state->color_encoding,
+                                       state->color_range, fb_is_interlaced);
                fe->ops->set_src_buf_dimensions(fe, src_w, src_h,
                                                fb->format->format,
                                                fb_is_interlaced);
@@ -886,6 +903,16 @@ struct dpu_plane *dpu_plane_init(struct drm_device *drm,
        if (ret)
                goto err;
 
+       ret = drm_plane_create_color_properties(plane,
+                                       BIT(DRM_COLOR_YCBCR_BT601) |
+                                       BIT(DRM_COLOR_YCBCR_BT709),
+                                       BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+                                       BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+                                       DRM_COLOR_YCBCR_BT601,
+                                       DRM_COLOR_YCBCR_FULL_RANGE);
+       if (ret)
+               goto err;
+
        return dpu_plane;
 
 err:
index 84b9f69..b8dacd8 100644 (file)
@@ -256,8 +256,11 @@ fetchdecode_set_src_buf_dimensions(struct dpu_fetchunit *fu,
        mutex_unlock(&fu->mutex);
 }
 
-static void
-fetchdecode_set_fmt(struct dpu_fetchunit *fu, u32 fmt, bool deinterlace)
+static void fetchdecode_set_fmt(struct dpu_fetchunit *fu,
+                               u32 fmt,
+                               enum drm_color_encoding color_encoding,
+                               enum drm_color_range color_range,
+                               bool deinterlace)
 {
        u32 val, bits, shift;
        bool is_planar_yuv = false, is_rastermode_yuv422 = false;
@@ -318,17 +321,18 @@ fetchdecode_set_fmt(struct dpu_fetchunit *fu, u32 fmt, bool deinterlace)
 
        val = dpu_fu_read(fu, LAYERPROPERTY0);
        val &= ~YUVCONVERSIONMODE_MASK;
-       if (need_csc)
-               /*
-                * assuming fetchdecode always ouputs RGB pixel formats
-                *
-                * FIXME:
-                * determine correct standard here - ITU601 or ITU601_FR
-                * or ITU709
-                */
-               val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__ITU601_FR);
-       else
+       if (need_csc) {
+               /* assuming fetchdecode always ouputs RGB pixel formats */
+               if (color_encoding == DRM_COLOR_YCBCR_BT709)
+                       val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__ITU709);
+               else if (color_encoding == DRM_COLOR_YCBCR_BT601 &&
+                        color_range == DRM_COLOR_YCBCR_FULL_RANGE)
+                       val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__ITU601_FR);
+               else
+                       val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__ITU601);
+       } else {
                val |= YUVCONVERSIONMODE(YUVCONVERSIONMODE__OFF);
+       }
        dpu_fu_write(fu, val, LAYERPROPERTY0);
        mutex_unlock(&fu->mutex);
 
index dc662f3..a0e8d1b 100644 (file)
@@ -79,7 +79,11 @@ fetcheco_set_src_buf_dimensions(struct dpu_fetchunit *fu,
        mutex_unlock(&fu->mutex);
 }
 
-static void fetcheco_set_fmt(struct dpu_fetchunit *fu, u32 fmt, bool unused)
+static void fetcheco_set_fmt(struct dpu_fetchunit *fu,
+                            u32 fmt,
+                            enum drm_color_encoding unused1,
+                            enum drm_color_range unused2,
+                            bool unused3)
 {
        u32 val, bits, shift;
        int i, hsub, vsub;
index b6e64a7..d51cec4 100644 (file)
@@ -68,7 +68,11 @@ fetchlayer_set_src_buf_dimensions(struct dpu_fetchunit *fu,
        mutex_unlock(&fu->mutex);
 }
 
-static void fetchlayer_set_fmt(struct dpu_fetchunit *fu, u32 fmt, bool unused)
+static void fetchlayer_set_fmt(struct dpu_fetchunit *fu,
+                              u32 fmt,
+                              enum drm_color_encoding color_encoding,
+                              enum drm_color_range color_range,
+                              bool unused)
 {
        u32 val, bits, shift;
        int i, sub_id = fu->sub_id;
index ff0f318..ecd1966 100644 (file)
@@ -69,7 +69,10 @@ fetchwarp_set_src_buf_dimensions(struct dpu_fetchunit *fu,
 }
 
 static void fetchwarp_set_fmt(struct dpu_fetchunit *fu,
-                             u32 fmt, bool unused)
+                             u32 fmt,
+                             enum drm_color_encoding color_encoding,
+                             enum drm_color_range color_range,
+                             bool unused)
 {
        u32 val, bits, shift;
        int i, sub_id = fu->sub_id;
index a1bd1f2..1657986 100644 (file)
@@ -475,7 +475,10 @@ struct dpu_fetchunit_ops {
                                       unsigned int w, unsigned int h, u32 fmt,
                                       bool deinterlace);
 
-       void (*set_fmt)(struct dpu_fetchunit *fu, u32 fmt, bool deinterlace);
+       void (*set_fmt)(struct dpu_fetchunit *fu, u32 fmt,
+                       enum drm_color_encoding color_encoding,
+                       enum drm_color_range color_range,
+                       bool deinterlace);
 
        void (*set_pixel_blend_mode)(struct dpu_fetchunit *fu,
                                     unsigned int pixel_blend_mode, u16 alpha,