#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>
__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 *
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)
{
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);
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,
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);
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:
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;
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);
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,