aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Yao <mark.yao@rock-chips.com>2015-07-20 04:16:49 -0400
committerMark Yao <mark.yao@rock-chips.com>2015-08-26 02:16:26 -0400
commit84c7f8ca43000ee97e556bddbbc4543e2514239d (patch)
tree1df60a1138258c2a69141223f98472cbaac49618
parentacf8c3e0a9eb5658e6ac4379cba51dba9b941083 (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.c56
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
396static 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
396static bool is_alpha_support(uint32_t format) 408static 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);