From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752200AbbFZKIO (ORCPT ); Fri, 26 Jun 2015 06:08:14 -0400 Received: from regular1.263xmail.com ([211.150.99.134]:39286 "EHLO regular1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751981AbbFZKHz (ORCPT ); Fri, 26 Jun 2015 06:07:55 -0400 X-263anti-spam: KSV:0; X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-KSVirus-check: 0 X-ABS-CHECKED: 4 X-ADDR-CHECKED: 0 X-RL-SENDER: mark.yao@rock-chips.com X-SENDER-IP: 43.226.228.192 X-LOGIN-NAME: mark.yao@rock-chips.com X-UNIQUE-TAG: <0df94272e6619bee2bedd07cf37685aa> X-ATTACHMENT-NUM: 0 X-DNS-TYPE: 0 From: Mark Yao To: dri-devel@lists.freedesktop.org Cc: David Airlie , Heiko Stuebner , Daniel Kurtz , Mark Yao , Philipp Zabel , Daniel Vetter , Rob Clark , linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, tfiga@chromium.org, sandy.huang@rock-chips.com, dkm@rock-chips.com, zwl@rock-chips.com, xw@rock-chips.com Subject: [PATCH v2 2/5] drm/rockchip: vop: fix yuv plane support Date: Fri, 26 Jun 2015 18:07:26 +0800 Message-Id: <1435313249-4549-3-git-send-email-mark.yao@rock-chips.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com> References: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org vop support yuv with NV12, NV16 and NV24, only 2 plane yuv. Signed-off-by: Mark Yao Changes in v2: - Uv buffer not support odd offset, align it. - Fix error display when move yuv image. --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 63 ++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 3c9f4f3..6ca08f8 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -373,6 +373,18 @@ static enum vop_data_format vop_convert_format(uint32_t format) } } +static bool is_yuv_support(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV24: + return true; + default: + return false; + } +} + static bool is_alpha_support(uint32_t format) { switch (format) { @@ -577,16 +589,21 @@ static int vop_update_plane_event(struct drm_plane *plane, struct vop *vop = to_vop(crtc); struct drm_gem_object *obj; struct rockchip_gem_object *rk_obj; + struct drm_gem_object *uv_obj; + struct rockchip_gem_object *rk_uv_obj; unsigned long offset; unsigned int actual_w; unsigned int actual_h; unsigned int dsp_stx; unsigned int dsp_sty; unsigned int y_vir_stride; + unsigned int uv_vir_stride; dma_addr_t yrgb_mst; + dma_addr_t uv_mst; enum vop_data_format format; uint32_t val; bool is_alpha; + bool is_yuv; bool visible; int ret; struct drm_rect dest = { @@ -608,6 +625,12 @@ static int vop_update_plane_event(struct drm_plane *plane, }; bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY; + if (drm_format_num_planes(fb->pixel_format) > 2) { + DRM_ERROR("unsupport more than 2 plane format[%08x]\n", + fb->pixel_format); + return -EINVAL; + } + ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip, DRM_PLANE_HELPER_NO_SCALING, @@ -624,28 +647,52 @@ static int vop_update_plane_event(struct drm_plane *plane, if (format < 0) return format; + is_yuv = is_yuv_support(fb->pixel_format); + obj = rockchip_fb_get_gem_obj(fb, 0); if (!obj) { DRM_ERROR("fail to get rockchip gem object from framebuffer\n"); return -EINVAL; } + if (is_yuv) { + src.x1 &= (~1) << 16; + src.y1 &= (~1) << 16; + } + rk_obj = to_rockchip_obj(obj); actual_w = (src.x2 - src.x1) >> 16; actual_h = (src.y2 - src.y1) >> 16; - crtc_x = max(0, crtc_x); - crtc_y = max(0, crtc_y); - dsp_stx = crtc_x + crtc->mode.htotal - crtc->mode.hsync_start; - dsp_sty = crtc_y + crtc->mode.vtotal - crtc->mode.vsync_start; + dsp_stx = dest.x1 + crtc->mode.htotal - crtc->mode.hsync_start; + dsp_sty = dest.y1 + crtc->mode.vtotal - crtc->mode.vsync_start; - offset = (src.x1 >> 16) * (fb->bits_per_pixel >> 3); + offset = (src.x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0); offset += (src.y1 >> 16) * fb->pitches[0]; - yrgb_mst = rk_obj->dma_addr + offset; + yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; y_vir_stride = fb->pitches[0] >> 2; + if (is_yuv) { + 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); + + uv_obj = rockchip_fb_get_gem_obj(fb, 1); + if (!uv_obj) { + DRM_ERROR("fail to get uv object from framebuffer\n"); + return -EINVAL; + } + rk_uv_obj = to_rockchip_obj(uv_obj); + uv_vir_stride = fb->pitches[1] >> 2; + + offset = (src.x1 >> 16) * bpp / hsub; + offset += (src.y1 >> 16) * fb->pitches[1] / vsub; + + uv_mst = rk_uv_obj->dma_addr + offset + fb->offsets[1]; + } + /* * If this plane update changes the plane's framebuffer, (or more * precisely, if this update has a different framebuffer than the last @@ -681,6 +728,10 @@ static int vop_update_plane_event(struct drm_plane *plane, VOP_WIN_SET(vop, win, format, format); VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride); VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst); + if (is_yuv) { + VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride); + VOP_WIN_SET(vop, win, uv_mst, uv_mst); + } val = (actual_h - 1) << 16; val |= (actual_w - 1) & 0xffff; VOP_WIN_SET(vop, win, act_info, val); -- 1.7.9.5