Message ID | 20180215053300.70482-2-dcastagna@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Daniele, Thank you for the patch! Yet something to improve: [auto build test ERROR on rockchip/for-next] [also build test ERROR on v4.16-rc1 next-20180216] [cannot apply to drm/drm-next] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Daniele-Castagna/drm-rockchip-YUV-overlays-BT-601-color-conversion/20180216-233006 base: https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next config: arm64-defconfig (attached as .config) compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=arm64 All error/warnings (new ones prefixed by >>): drivers/gpu//drm/rockchip/rockchip_drm_vop.c: In function 'vop_plane_atomic_update': >> drivers/gpu//drm/rockchip/rockchip_drm_vop.c:742:18: error: implicit declaration of function 'VOP_WIN_TO_INDEX'; did you mean 'CAP_TO_INDEX'? [-Werror=implicit-function-declaration] int win_index = VOP_WIN_TO_INDEX(vop_win); ^~~~~~~~~~~~~~~~ CAP_TO_INDEX cc1: some warnings being treated as errors -- >> drivers/gpu//drm/rockchip/rockchip_vop_reg.c:468:9: error: 'rk3399_vop_win_data' undeclared here (not in a function); did you mean 'rk3368_vop_win_data'? .win = rk3399_vop_win_data, ^~~~~~~~~~~~~~~~~~~ rk3368_vop_win_data In file included from arch/arm64/include/asm/sysreg.h:669:0, from arch/arm64/include/asm/cputype.h:116, from arch/arm64/include/asm/cache.h:19, from include/linux/cache.h:6, from include/linux/printk.h:9, from include/linux/kernel.h:14, from include/linux/list.h:9, from include/linux/agp_backend.h:33, from include/drm/drmP.h:35, from drivers/gpu//drm/rockchip/rockchip_vop_reg.c:15: >> include/linux/build_bug.h:29:45: error: bit-field '<anonymous>' width not an integer constant #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); })) ^ include/linux/compiler-gcc.h:65:28: note: in expansion of macro 'BUILD_BUG_ON_ZERO' #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) ^~~~~~~~~~~~~~~~~ include/linux/kernel.h:71:59: note: in expansion of macro '__must_be_array' #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) ^~~~~~~~~~~~~~~ >> drivers/gpu//drm/rockchip/rockchip_vop_reg.c:469:14: note: in expansion of macro 'ARRAY_SIZE' .win_size = ARRAY_SIZE(rk3399_vop_win_data), ^~~~~~~~~~ -- drivers/gpu/drm/rockchip/rockchip_vop_reg.c:468:9: error: 'rk3399_vop_win_data' undeclared here (not in a function); did you mean 'rk3368_vop_win_data'? .win = rk3399_vop_win_data, ^~~~~~~~~~~~~~~~~~~ rk3368_vop_win_data In file included from arch/arm64/include/asm/sysreg.h:669:0, from arch/arm64/include/asm/cputype.h:116, from arch/arm64/include/asm/cache.h:19, from include/linux/cache.h:6, from include/linux/printk.h:9, from include/linux/kernel.h:14, from include/linux/list.h:9, from include/linux/agp_backend.h:33, from include/drm/drmP.h:35, from drivers/gpu/drm/rockchip/rockchip_vop_reg.c:15: >> include/linux/build_bug.h:29:45: error: bit-field '<anonymous>' width not an integer constant #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); })) ^ include/linux/compiler-gcc.h:65:28: note: in expansion of macro 'BUILD_BUG_ON_ZERO' #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) ^~~~~~~~~~~~~~~~~ include/linux/kernel.h:71:59: note: in expansion of macro '__must_be_array' #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) ^~~~~~~~~~~~~~~ drivers/gpu/drm/rockchip/rockchip_vop_reg.c:469:14: note: in expansion of macro 'ARRAY_SIZE' .win_size = ARRAY_SIZE(rk3399_vop_win_data), ^~~~~~~~~~ vim +742 drivers/gpu//drm/rockchip/rockchip_drm_vop.c 719 720 static void vop_plane_atomic_update(struct drm_plane *plane, 721 struct drm_plane_state *old_state) 722 { 723 struct drm_plane_state *state = plane->state; 724 struct drm_crtc *crtc = state->crtc; 725 struct vop_win *vop_win = to_vop_win(plane); 726 const struct vop_win_data *win = vop_win->data; 727 struct vop *vop = to_vop(state->crtc); 728 struct drm_framebuffer *fb = state->fb; 729 unsigned int actual_w, actual_h; 730 unsigned int dsp_stx, dsp_sty; 731 uint32_t act_info, dsp_info, dsp_st; 732 struct drm_rect *src = &state->src; 733 struct drm_rect *dest = &state->dst; 734 struct drm_gem_object *obj, *uv_obj; 735 struct rockchip_gem_object *rk_obj, *rk_uv_obj; 736 unsigned long offset; 737 dma_addr_t dma_addr; 738 uint32_t val; 739 bool rb_swap; 740 int format; 741 int is_yuv = is_yuv_support(fb->format->format); > 742 int win_index = VOP_WIN_TO_INDEX(vop_win); 743 int i; 744 745 /* 746 * can't update plane when vop is disabled. 747 */ 748 if (WARN_ON(!crtc)) 749 return; 750 751 if (WARN_ON(!vop->is_enabled)) 752 return; 753 754 if (!state->visible) { 755 vop_plane_atomic_disable(plane, old_state); 756 return; 757 } 758 759 obj = rockchip_fb_get_gem_obj(fb, 0); 760 rk_obj = to_rockchip_obj(obj); 761 762 actual_w = drm_rect_width(src) >> 16; 763 actual_h = drm_rect_height(src) >> 16; 764 act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); 765 766 dsp_info = (drm_rect_height(dest) - 1) << 16; 767 dsp_info |= (drm_rect_width(dest) - 1) & 0xffff; 768 769 dsp_stx = dest->x1 + crtc->mode.htotal - crtc->mode.hsync_start; 770 dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start; 771 dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); 772 773 offset = (src->x1 >> 16) * fb->format->cpp[0]; 774 offset += (src->y1 >> 16) * fb->pitches[0]; 775 dma_addr = rk_obj->dma_addr + offset + fb->offsets[0]; 776 777 format = vop_convert_format(fb->format->format); 778 779 spin_lock(&vop->reg_lock); 780 781 VOP_WIN_SET(vop, win, format, format); 782 VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); 783 VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); 784 785 if (!win_index) { 786 VOP_YUV2YUV_SET(vop, win0_y2r_en, is_yuv); 787 } else if (win_index == 1) { 788 VOP_YUV2YUV_SET(vop, win1_y2r_en, is_yuv); 789 } 790 791 if (is_yuv) { 792 int hsub = drm_format_horz_chroma_subsampling(fb->format->format); 793 int vsub = drm_format_vert_chroma_subsampling(fb->format->format); 794 int bpp = fb->format->cpp[1]; 795 796 uv_obj = rockchip_fb_get_gem_obj(fb, 1); 797 rk_uv_obj = to_rockchip_obj(uv_obj); 798 799 offset = (src->x1 >> 16) * bpp / hsub; 800 offset += (src->y1 >> 16) * fb->pitches[1] / vsub; 801 802 dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; 803 VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4)); 804 VOP_WIN_SET(vop, win, uv_mst, dma_addr); 805 806 for (i = 0; i < 12; i++) { 807 if (!win_index) { 808 VOP_YUV2YUV_SET(vop, 809 win0_y2r_coefficients[i], 810 bt601_yuv2rgb[i]); 811 } else { 812 VOP_YUV2YUV_SET(vop, 813 win1_y2r_coefficients[i], 814 bt601_yuv2rgb[i]); 815 } 816 } 817 } 818 819 if (win->phy->scl) 820 scl_vop_cal_scl_fac(vop, win, actual_w, actual_h, 821 drm_rect_width(dest), drm_rect_height(dest), 822 fb->format->format); 823 824 VOP_WIN_SET(vop, win, act_info, act_info); 825 VOP_WIN_SET(vop, win, dsp_info, dsp_info); 826 VOP_WIN_SET(vop, win, dsp_st, dsp_st); 827 828 rb_swap = has_rb_swapped(fb->format->format); 829 VOP_WIN_SET(vop, win, rb_swap, rb_swap); 830 831 if (is_alpha_support(fb->format->format)) { 832 VOP_WIN_SET(vop, win, dst_alpha_ctl, 833 DST_FACTOR_M0(ALPHA_SRC_INVERSE)); 834 val = SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL) | 835 SRC_ALPHA_M0(ALPHA_STRAIGHT) | 836 SRC_BLEND_M0(ALPHA_PER_PIX) | 837 SRC_ALPHA_CAL_M0(ALPHA_NO_SATURATION) | 838 SRC_FACTOR_M0(ALPHA_ONE); 839 VOP_WIN_SET(vop, win, src_alpha_ctl, val); 840 } else { 841 VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0)); 842 } 843 844 VOP_WIN_SET(vop, win, enable, 1); 845 spin_unlock(&vop->reg_lock); 846 } 847 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Thu, Feb 15, 2018 at 12:32:51AM -0500, Daniele Castagna wrote: > Currently NV12 hardware overlays scheduled with atomic interface are > converted to RGB using a color space conversion different than BT.601. > > The result is that colors of NV12 buffers composited with Mali don't > match colors of YUV hardware overlays. > > Running modetest with an NV12 plane also shows colors are incorrect > if compared to an RGB overlay that represents the same color pattern. > > This CL adds support for YUV2YUV color space conversion (CSC) module on > rockchip and enables the YUV2RGB part that allows to specify a 4x3 > matrix to convert the colors. > > The matrix is set to BT.601 coefficients to align to Mali and to what > modetest expects. Hey Daniele, Apologies for missing this set. > > TEST=modetest -M rockchip -s 34@30:2400x1600 -P 30:640x480+650+10@NV12 -P 30:640x480+10+10@XR24 > > Change-Id: Ia5a3b4793229e2c63f79f9f414d1cbe6ccc63fc1 It's usually good form to strip out the gerrit Change-Id from the commit message. > Tested-by: Daniele Castagna <dcastagna@chromium.org> > Reviewed-by: Daniele Castagna <dcastagna@chromium.org> > Reviewed-by: Kristian H. Kristensen <hoegsberg@chromium.org> > --- > drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 40 ++++++++++++++++++++- > drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 9 +++++ > drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 39 ++++++++++++++++++-- > 3 files changed, 85 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c > index ba7505292b786..ea43ab797f555 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c > @@ -50,6 +50,10 @@ > vop_reg_set(vop, &win->phy->scl->ext->name, \ > win->base, ~0, v, #name) > > +#define VOP_YUV2YUV_SET(x, name, v) \ > + if ((x)->data->yuv2yuv) \ > + vop_reg_set(vop, &vop->data->yuv2yuv->name, 0, ~0, v, #name) > + > #define VOP_INTR_SET_MASK(vop, name, mask, v) \ > vop_reg_set(vop, &vop->data->intr->name, 0, mask, v, #name) > > @@ -79,6 +83,18 @@ > #define to_vop(x) container_of(x, struct vop, crtc) > #define to_vop_win(x) container_of(x, struct vop_win, base) > > +/* > + * The coefficients of the following matrix are all fixed points. > + * The format is S2.10 for the 3x3 part of the matrix, and S9.12 for the offsets. > + * They are all represented in two's complement. > + */ > +static const uint32_t bt601_yuv2rgb[] = { > + 0x4A8, 0x0, 0x662, > + 0x4A8, 0x1E6F, 0x1CBF, > + 0x4A8, 0x812, 0x0, > + 0x321168, 0x0877CF, 0x2EB127 > +}; > + > enum vop_pending { > VOP_PENDING_FB_UNREF, > }; > @@ -722,6 +738,9 @@ static void vop_plane_atomic_update(struct drm_plane *plane, > uint32_t val; > bool rb_swap; > int format; > + int is_yuv = is_yuv_support(fb->format->format); > + int win_index = VOP_WIN_TO_INDEX(vop_win); > + int i; > > /* > * can't update plane when vop is disabled. > @@ -762,7 +781,14 @@ static void vop_plane_atomic_update(struct drm_plane *plane, > VOP_WIN_SET(vop, win, format, format); > VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); > VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); > - if (is_yuv_support(fb->format->format)) { > + > + if (!win_index) { > + VOP_YUV2YUV_SET(vop, win0_y2r_en, is_yuv); > + } else if (win_index == 1) { > + VOP_YUV2YUV_SET(vop, win1_y2r_en, is_yuv); > + } > + > + if (is_yuv) { > int hsub = drm_format_horz_chroma_subsampling(fb->format->format); > int vsub = drm_format_vert_chroma_subsampling(fb->format->format); > int bpp = fb->format->cpp[1]; > @@ -776,6 +802,18 @@ static void vop_plane_atomic_update(struct drm_plane *plane, > dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; > VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4)); > VOP_WIN_SET(vop, win, uv_mst, dma_addr); > + > + for (i = 0; i < 12; i++) { > + if (!win_index) { > + VOP_YUV2YUV_SET(vop, > + win0_y2r_coefficients[i], > + bt601_yuv2rgb[i]); > + } else { > + VOP_YUV2YUV_SET(vop, > + win1_y2r_coefficients[i], > + bt601_yuv2rgb[i]); > + } > + } > } > > if (win->phy->scl) > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > index 56bbd2e2a8efb..aa8a5d2690376 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h > @@ -79,6 +79,14 @@ struct vop_misc { > struct vop_reg global_regdone_en; > }; > > +struct vop_yuv2yuv { > + struct vop_reg win0_y2r_en; > + struct vop_reg win0_y2r_coefficients[12]; > + > + struct vop_reg win1_y2r_en; > + struct vop_reg win1_y2r_coefficients[12]; > +}; struct vop_yuv2yuv { struct { struct vop_reg y2r_en; struct vop_reg y2r_coefficients[12]; } regs[2]; }; Then add win_index to the macro above and you can avoid the if (!win_index) checks everywhere. Bonus points if you #define the '2' and '12' as something more meaningful > + > struct vop_intr { > const int *intrs; > uint32_t nintrs; > @@ -157,6 +165,7 @@ struct vop_data { > const struct vop_misc *misc; > const struct vop_modeset *modeset; > const struct vop_output *output; > + const struct vop_yuv2yuv *yuv2yuv; > const struct vop_win_data *win; > unsigned int win_size; > > diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c > index 2e4eea3459fe6..be9c414e2e4bc 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c > +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c > @@ -422,6 +422,40 @@ static const struct vop_output rk3399_output = { > .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), > }; > > +static const struct vop_yuv2yuv rk3399_vop_yuv2yuv = { > + .win0_y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1), > + .win0_y2r_coefficients = { > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 0, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 0, 0xffff, 16), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 4, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 4, 0xffff, 16), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 8, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 8, 0xffff, 16), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 12, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 12, 0xffff, 16), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 16, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 20, 0xffffffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 24, 0xffffffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 28, 0xffffffff, 0), > + }, > + > + .win1_y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9), > + .win1_y2r_coefficients = { > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 0, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 0, 0xffff, 16), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 4, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 4, 0xffff, 16), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 8, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 8, 0xffff, 16), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 12, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 12, 0xffff, 16), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 16, 0xffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 20, 0xffffffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 24, 0xffffffff, 0), > + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 28, 0xffffffff, 0), > + }, > +}; > + > static const struct vop_data rk3399_vop_big = { > .version = VOP_VERSION(3, 5), > .feature = VOP_FEATURE_OUTPUT_RGB10, > @@ -430,8 +464,9 @@ static const struct vop_data rk3399_vop_big = { > .modeset = &rk3288_modeset, > .output = &rk3399_output, > .misc = &rk3368_misc, > - .win = rk3368_vop_win_data, > - .win_size = ARRAY_SIZE(rk3368_vop_win_data), > + .yuv2yuv = &rk3399_vop_yuv2yuv, > + .win = rk3399_vop_win_data, > + .win_size = ARRAY_SIZE(rk3399_vop_win_data), > }; > > static const struct vop_win_data rk3399_vop_lit_win_data[] = { > -- > 2.16.1.291.g4437f3f132-goog > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index ba7505292b786..ea43ab797f555 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -50,6 +50,10 @@ vop_reg_set(vop, &win->phy->scl->ext->name, \ win->base, ~0, v, #name) +#define VOP_YUV2YUV_SET(x, name, v) \ + if ((x)->data->yuv2yuv) \ + vop_reg_set(vop, &vop->data->yuv2yuv->name, 0, ~0, v, #name) + #define VOP_INTR_SET_MASK(vop, name, mask, v) \ vop_reg_set(vop, &vop->data->intr->name, 0, mask, v, #name) @@ -79,6 +83,18 @@ #define to_vop(x) container_of(x, struct vop, crtc) #define to_vop_win(x) container_of(x, struct vop_win, base) +/* + * The coefficients of the following matrix are all fixed points. + * The format is S2.10 for the 3x3 part of the matrix, and S9.12 for the offsets. + * They are all represented in two's complement. + */ +static const uint32_t bt601_yuv2rgb[] = { + 0x4A8, 0x0, 0x662, + 0x4A8, 0x1E6F, 0x1CBF, + 0x4A8, 0x812, 0x0, + 0x321168, 0x0877CF, 0x2EB127 +}; + enum vop_pending { VOP_PENDING_FB_UNREF, }; @@ -722,6 +738,9 @@ static void vop_plane_atomic_update(struct drm_plane *plane, uint32_t val; bool rb_swap; int format; + int is_yuv = is_yuv_support(fb->format->format); + int win_index = VOP_WIN_TO_INDEX(vop_win); + int i; /* * can't update plane when vop is disabled. @@ -762,7 +781,14 @@ static void vop_plane_atomic_update(struct drm_plane *plane, VOP_WIN_SET(vop, win, format, format); VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4)); VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); - if (is_yuv_support(fb->format->format)) { + + if (!win_index) { + VOP_YUV2YUV_SET(vop, win0_y2r_en, is_yuv); + } else if (win_index == 1) { + VOP_YUV2YUV_SET(vop, win1_y2r_en, is_yuv); + } + + if (is_yuv) { int hsub = drm_format_horz_chroma_subsampling(fb->format->format); int vsub = drm_format_vert_chroma_subsampling(fb->format->format); int bpp = fb->format->cpp[1]; @@ -776,6 +802,18 @@ static void vop_plane_atomic_update(struct drm_plane *plane, dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1]; VOP_WIN_SET(vop, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4)); VOP_WIN_SET(vop, win, uv_mst, dma_addr); + + for (i = 0; i < 12; i++) { + if (!win_index) { + VOP_YUV2YUV_SET(vop, + win0_y2r_coefficients[i], + bt601_yuv2rgb[i]); + } else { + VOP_YUV2YUV_SET(vop, + win1_y2r_coefficients[i], + bt601_yuv2rgb[i]); + } + } } if (win->phy->scl) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 56bbd2e2a8efb..aa8a5d2690376 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -79,6 +79,14 @@ struct vop_misc { struct vop_reg global_regdone_en; }; +struct vop_yuv2yuv { + struct vop_reg win0_y2r_en; + struct vop_reg win0_y2r_coefficients[12]; + + struct vop_reg win1_y2r_en; + struct vop_reg win1_y2r_coefficients[12]; +}; + struct vop_intr { const int *intrs; uint32_t nintrs; @@ -157,6 +165,7 @@ struct vop_data { const struct vop_misc *misc; const struct vop_modeset *modeset; const struct vop_output *output; + const struct vop_yuv2yuv *yuv2yuv; const struct vop_win_data *win; unsigned int win_size; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 2e4eea3459fe6..be9c414e2e4bc 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -422,6 +422,40 @@ static const struct vop_output rk3399_output = { .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), }; +static const struct vop_yuv2yuv rk3399_vop_yuv2yuv = { + .win0_y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 1), + .win0_y2r_coefficients = { + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 0, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 0, 0xffff, 16), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 4, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 4, 0xffff, 16), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 8, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 8, 0xffff, 16), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 12, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 12, 0xffff, 16), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 16, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 20, 0xffffffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 24, 0xffffffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 28, 0xffffffff, 0), + }, + + .win1_y2r_en = VOP_REG(RK3399_YUV2YUV_WIN, 0x1, 9), + .win1_y2r_coefficients = { + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 0, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 0, 0xffff, 16), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 4, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 4, 0xffff, 16), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 8, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 8, 0xffff, 16), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 12, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 12, 0xffff, 16), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 16, 0xffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 20, 0xffffffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 24, 0xffffffff, 0), + VOP_REG(RK3399_WIN1_YUV2YUV_Y2R + 28, 0xffffffff, 0), + }, +}; + static const struct vop_data rk3399_vop_big = { .version = VOP_VERSION(3, 5), .feature = VOP_FEATURE_OUTPUT_RGB10, @@ -430,8 +464,9 @@ static const struct vop_data rk3399_vop_big = { .modeset = &rk3288_modeset, .output = &rk3399_output, .misc = &rk3368_misc, - .win = rk3368_vop_win_data, - .win_size = ARRAY_SIZE(rk3368_vop_win_data), + .yuv2yuv = &rk3399_vop_yuv2yuv, + .win = rk3399_vop_win_data, + .win_size = ARRAY_SIZE(rk3399_vop_win_data), }; static const struct vop_win_data rk3399_vop_lit_win_data[] = {