drm/rockchip: support 10bit yuv format
authorMark Yao <mark.yao@rock-chips.com>
Wed, 23 Nov 2016 08:03:51 +0000 (16:03 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 24 Nov 2016 04:59:41 +0000 (12:59 +0800)
Change-Id: I7c1f9c3b0a4b8e711d8ce198af9b94bd7639bf17
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/gpu/drm/rockchip/rockchip_drm_fb.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.h
drivers/gpu/drm/rockchip/rockchip_vop_reg.c

index 22dd5bcefda9fca745cf08a7ee5601ad3a17d2ec..3f5f8c42fda4793e86dc37be299b573da36c5a87 100644 (file)
@@ -168,6 +168,8 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                unsigned int width = mode_cmd->width / (i ? hsub : 1);
                unsigned int height = mode_cmd->height / (i ? vsub : 1);
                unsigned int min_size;
+               unsigned int bpp =
+                       drm_format_plane_bpp(mode_cmd->pixel_format, i);
 
                obj = drm_gem_object_lookup(dev, file_priv,
                                            mode_cmd->handles[i]);
@@ -178,9 +180,7 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
                }
 
                min_size = (height - 1) * mode_cmd->pitches[i] +
-                       mode_cmd->offsets[i] +
-                       width * drm_format_plane_cpp(mode_cmd->pixel_format, i);
-
+                       mode_cmd->offsets[i] + roundup(width * bpp, 8) / 8;
                if (obj->size < min_size) {
                        drm_gem_object_unreference_unlocked(obj);
                        ret = -EINVAL;
index b5e8126fd7199f37ea85baa08e6e042d90f6fe62..e45a8b7f33fc33d6c7b3ec712500985de53e3a5b 100644 (file)
@@ -328,10 +328,13 @@ static enum vop_data_format vop_convert_format(uint32_t format)
        case DRM_FORMAT_BGR565:
                return VOP_FMT_RGB565;
        case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV12_10:
                return VOP_FMT_YUV420SP;
        case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV16_10:
                return VOP_FMT_YUV422SP;
        case DRM_FORMAT_NV24:
+       case DRM_FORMAT_NV24_10:
                return VOP_FMT_YUV444SP;
        default:
                DRM_ERROR("unsupport format[%08x]\n", format);
@@ -343,8 +346,23 @@ static bool is_yuv_support(uint32_t format)
 {
        switch (format) {
        case DRM_FORMAT_NV12:
+       case DRM_FORMAT_NV12_10:
        case DRM_FORMAT_NV16:
+       case DRM_FORMAT_NV16_10:
        case DRM_FORMAT_NV24:
+       case DRM_FORMAT_NV24_10:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool is_yuv_10bit(uint32_t format)
+{
+       switch (format) {
+       case DRM_FORMAT_NV12_10:
+       case DRM_FORMAT_NV16_10:
+       case DRM_FORMAT_NV24_10:
                return true;
        default:
                return false;
@@ -863,7 +881,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        if (is_yuv_support(fb->pixel_format) && ((src->x1 >> 16) % 2))
                return -EINVAL;
 
-       offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
+       offset = (src->x1 >> 16) * drm_format_plane_bpp(fb->pixel_format, 0) / 8;
        if (state->rotation & BIT(DRM_REFLECT_Y))
                offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
        else
@@ -874,9 +892,9 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        if (is_yuv_support(fb->pixel_format)) {
                int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
                int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
-               int bpp = drm_format_plane_cpp(fb->pixel_format, 1);
+               int bpp = drm_format_plane_bpp(fb->pixel_format, 1);
 
-               offset = (src->x1 >> 16) * bpp / hsub;
+               offset = (src->x1 >> 16) * bpp / hsub / 8;
                offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
 
                dma_addr = rockchip_fb_get_dma_addr(fb, 1);
@@ -970,6 +988,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
                VOP_WIN_SET(vop, win, uv_vir, fb->pitches[1] >> 2);
                VOP_WIN_SET(vop, win, uv_mst, vop_plane_state->uv_mst);
        }
+       VOP_WIN_SET(vop, win, fmt_10, is_yuv_10bit(fb->pixel_format));
 
        scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
                            drm_rect_width(dest), drm_rect_height(dest),
index 349338ed01cd8cb5016b732de2708d021f6097b6..85a3bc67d2b6150e135c886222d6784262898342 100644 (file)
@@ -212,6 +212,7 @@ struct vop_win_phy {
        struct vop_reg gate;
        struct vop_reg enable;
        struct vop_reg format;
+       struct vop_reg fmt_10;
        struct vop_reg xmirror;
        struct vop_reg ymirror;
        struct vop_reg rb_swap;
index 85fc43d45e0730f53c1ae1ac5575ff3975adf055..edf4454441da88c6bb36740851581030ba13edd2 100644 (file)
@@ -53,6 +53,9 @@ static const uint32_t formats_win_full[] = {
        DRM_FORMAT_NV12,
        DRM_FORMAT_NV16,
        DRM_FORMAT_NV24,
+       DRM_FORMAT_NV12_10,
+       DRM_FORMAT_NV16_10,
+       DRM_FORMAT_NV24_10,
 };
 
 static const uint32_t formats_win_lite[] = {
@@ -104,6 +107,7 @@ static const struct vop_win_phy rk3288_win01_data = {
        .nformats = ARRAY_SIZE(formats_win_full),
        .enable = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 0),
        .format = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 1),
+       .fmt_10 = VOP_REG(RK3288_WIN0_CTRL0, 0x7, 4),
        .rb_swap = VOP_REG(RK3288_WIN0_CTRL0, 0x1, 12),
        .xmirror = VOP_REG_VER(RK3368_WIN0_CTRL0, 0x1, 21, 3, 2, -1),
        .ymirror = VOP_REG_VER(RK3368_WIN0_CTRL0, 0x1, 22, 3, 2, -1),