diff options
author | Mark Yao <mark.yao@rock-chips.com> | 2015-07-20 04:16:49 -0400 |
---|---|---|
committer | Mark Yao <mark.yao@rock-chips.com> | 2015-08-26 02:16:26 -0400 |
commit | 84c7f8ca43000ee97e556bddbbc4543e2514239d (patch) | |
tree | 1df60a1138258c2a69141223f98472cbaac49618 | |
parent | acf8c3e0a9eb5658e6ac4379cba51dba9b941083 (diff) |
drm/rockchip: vop: Add yuv plane support
vop support yuv with NV12, NV16 and NV24, only 2 plane yuv.
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index da72de9eb3d5..c1264d58b03b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c | |||
@@ -393,6 +393,18 @@ static enum vop_data_format vop_convert_format(uint32_t format) | |||
393 | } | 393 | } |
394 | } | 394 | } |
395 | 395 | ||
396 | static bool is_yuv_support(uint32_t format) | ||
397 | { | ||
398 | switch (format) { | ||
399 | case DRM_FORMAT_NV12: | ||
400 | case DRM_FORMAT_NV16: | ||
401 | case DRM_FORMAT_NV24: | ||
402 | return true; | ||
403 | default: | ||
404 | return false; | ||
405 | } | ||
406 | } | ||
407 | |||
396 | static bool is_alpha_support(uint32_t format) | 408 | static bool is_alpha_support(uint32_t format) |
397 | { | 409 | { |
398 | switch (format) { | 410 | switch (format) { |
@@ -598,17 +610,22 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
598 | struct vop *vop = to_vop(crtc); | 610 | struct vop *vop = to_vop(crtc); |
599 | struct drm_gem_object *obj; | 611 | struct drm_gem_object *obj; |
600 | struct rockchip_gem_object *rk_obj; | 612 | struct rockchip_gem_object *rk_obj; |
613 | struct drm_gem_object *uv_obj; | ||
614 | struct rockchip_gem_object *rk_uv_obj; | ||
601 | unsigned long offset; | 615 | unsigned long offset; |
602 | unsigned int actual_w; | 616 | unsigned int actual_w; |
603 | unsigned int actual_h; | 617 | unsigned int actual_h; |
604 | unsigned int dsp_stx; | 618 | unsigned int dsp_stx; |
605 | unsigned int dsp_sty; | 619 | unsigned int dsp_sty; |
606 | unsigned int y_vir_stride; | 620 | unsigned int y_vir_stride; |
621 | unsigned int uv_vir_stride = 0; | ||
607 | dma_addr_t yrgb_mst; | 622 | dma_addr_t yrgb_mst; |
623 | dma_addr_t uv_mst = 0; | ||
608 | enum vop_data_format format; | 624 | enum vop_data_format format; |
609 | uint32_t val; | 625 | uint32_t val; |
610 | bool is_alpha; | 626 | bool is_alpha; |
611 | bool rb_swap; | 627 | bool rb_swap; |
628 | bool is_yuv; | ||
612 | bool visible; | 629 | bool visible; |
613 | int ret; | 630 | int ret; |
614 | struct drm_rect dest = { | 631 | struct drm_rect dest = { |
@@ -643,6 +660,8 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
643 | 660 | ||
644 | is_alpha = is_alpha_support(fb->pixel_format); | 661 | is_alpha = is_alpha_support(fb->pixel_format); |
645 | rb_swap = has_rb_swapped(fb->pixel_format); | 662 | rb_swap = has_rb_swapped(fb->pixel_format); |
663 | is_yuv = is_yuv_support(fb->pixel_format); | ||
664 | |||
646 | format = vop_convert_format(fb->pixel_format); | 665 | format = vop_convert_format(fb->pixel_format); |
647 | if (format < 0) | 666 | if (format < 0) |
648 | return format; | 667 | return format; |
@@ -655,18 +674,47 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
655 | 674 | ||
656 | rk_obj = to_rockchip_obj(obj); | 675 | rk_obj = to_rockchip_obj(obj); |
657 | 676 | ||
677 | if (is_yuv) { | ||
678 | /* | ||
679 | * Src.x1 can be odd when do clip, but yuv plane start point | ||
680 | * need align with 2 pixel. | ||
681 | */ | ||
682 | val = (src.x1 >> 16) % 2; | ||
683 | src.x1 += val << 16; | ||
684 | src.x2 += val << 16; | ||
685 | } | ||
686 | |||
658 | actual_w = (src.x2 - src.x1) >> 16; | 687 | actual_w = (src.x2 - src.x1) >> 16; |
659 | actual_h = (src.y2 - src.y1) >> 16; | 688 | actual_h = (src.y2 - src.y1) >> 16; |
660 | 689 | ||
661 | dsp_stx = dest.x1 + crtc->mode.htotal - crtc->mode.hsync_start; | 690 | dsp_stx = dest.x1 + crtc->mode.htotal - crtc->mode.hsync_start; |
662 | dsp_sty = dest.y1 + crtc->mode.vtotal - crtc->mode.vsync_start; | 691 | dsp_sty = dest.y1 + crtc->mode.vtotal - crtc->mode.vsync_start; |
663 | 692 | ||
664 | offset = (src.x1 >> 16) * (fb->bits_per_pixel >> 3); | 693 | offset = (src.x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0); |
665 | offset += (src.y1 >> 16) * fb->pitches[0]; | 694 | offset += (src.y1 >> 16) * fb->pitches[0]; |
666 | yrgb_mst = rk_obj->dma_addr + offset; | ||
667 | 695 | ||
696 | yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; | ||
668 | y_vir_stride = fb->pitches[0] >> 2; | 697 | y_vir_stride = fb->pitches[0] >> 2; |
669 | 698 | ||
699 | if (is_yuv) { | ||
700 | int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); | ||
701 | int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); | ||
702 | int bpp = drm_format_plane_cpp(fb->pixel_format, 1); | ||
703 | |||
704 | uv_obj = rockchip_fb_get_gem_obj(fb, 1); | ||
705 | if (!uv_obj) { | ||
706 | DRM_ERROR("fail to get uv object from framebuffer\n"); | ||
707 | return -EINVAL; | ||
708 | } | ||
709 | rk_uv_obj = to_rockchip_obj(uv_obj); | ||
710 | uv_vir_stride = fb->pitches[1] >> 2; | ||
711 | |||
712 | offset = (src.x1 >> 16) * bpp / hsub; | ||
713 | offset += (src.y1 >> 16) * fb->pitches[1] / vsub; | ||
714 | |||
715 | uv_mst = rk_uv_obj->dma_addr + offset + fb->offsets[1]; | ||
716 | } | ||
717 | |||
670 | /* | 718 | /* |
671 | * If this plane update changes the plane's framebuffer, (or more | 719 | * If this plane update changes the plane's framebuffer, (or more |
672 | * precisely, if this update has a different framebuffer than the last | 720 | * precisely, if this update has a different framebuffer than the last |
@@ -702,6 +750,10 @@ static int vop_update_plane_event(struct drm_plane *plane, | |||
702 | VOP_WIN_SET(vop, win, format, format); | 750 | VOP_WIN_SET(vop, win, format, format); |
703 | VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride); | 751 | VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride); |
704 | VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst); | 752 | VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst); |
753 | if (is_yuv) { | ||
754 | VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride); | ||
755 | VOP_WIN_SET(vop, win, uv_mst, uv_mst); | ||
756 | } | ||
705 | val = (actual_h - 1) << 16; | 757 | val = (actual_h - 1) << 16; |
706 | val |= (actual_w - 1) & 0xffff; | 758 | val |= (actual_w - 1) & 0xffff; |
707 | VOP_WIN_SET(vop, win, act_info, val); | 759 | VOP_WIN_SET(vop, win, act_info, val); |