From patchwork Sat Sep 10 03:07:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: yao mark X-Patchwork-Id: 9324685 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5118760752 for ; Sat, 10 Sep 2016 03:08:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 42CF629FCF for ; Sat, 10 Sep 2016 03:08:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 310172A035; Sat, 10 Sep 2016 03:08:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.5 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, URIBL_BLACK autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9538529FCF for ; Sat, 10 Sep 2016 03:08:18 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1biYeP-0000W5-1p; Sat, 10 Sep 2016 03:08:17 +0000 Received: from regular1.263xmail.com ([211.150.99.133]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1biYe8-0000TA-Pm; Sat, 10 Sep 2016 03:08:03 +0000 Received: from mark.yao?rock-chips.com (unknown [192.168.167.154]) by regular1.263xmail.com (Postfix) with ESMTP id 5A6748E1D; Sat, 10 Sep 2016 11:07:35 +0800 (CST) X-263anti-spam: KSV:0; X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-KSVirus-check: 0 X-ABS-CHECKED: 4 X-ADDR-CHECKED4: 1 Received: from localhost.localdomain (localhost [127.0.0.1]) by smtp.263.net (Postfix) with ESMTP id 6CFE63A3; Sat, 10 Sep 2016 11:07:34 +0800 (CST) X-RL-SENDER: mark.yao@rock-chips.com X-FST-TO: airlied@linux.ie X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: mark.yao@rock-chips.com X-UNIQUE-TAG: X-ATTACHMENT-NUM: 0 X-SENDER: yzq@rock-chips.com X-DNS-TYPE: 0 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (Postfix) whith ESMTP id 21431OFN16V; Sat, 10 Sep 2016 11:07:35 +0800 (CST) From: Mark Yao To: David Airlie , Heiko Stuebner , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH] drm/rockchip: vop: support afbc format for rk3399 vop Date: Sat, 10 Sep 2016 11:07:32 +0800 Message-Id: <1473476852-25707-1-git-send-email-mark.yao@rock-chips.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1473474544-16248-3-git-send-email-mark.yao@rock-chips.com> References: <1473474544-16248-3-git-send-email-mark.yao@rock-chips.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160909_200801_694194_BE3BF635 X-CRM114-Status: GOOD ( 11.93 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Yao MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Rk3399 vop big can support one afbc decoder, the afbc decoder can select which overlay window use it. on vop hardware, we call afbc decoder as afbdc. afbdc window has some limit: 1, not support offset on source buffer. 2, if feed non-afbc buffer to afbc decoder, afbc decoder hardware would die, we need take care of using it. AFBC is a compressed format, means lower bandwidth consume, it's useful to improve performance. Signed-off-by: Mark Yao --- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 6 ++ drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 89 +++++++++++++++++++++++++++++ drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 13 +++++ drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 7 +++ 4 files changed, 115 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index ea39329..1e07fd6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -44,6 +44,12 @@ struct rockchip_crtc_funcs { struct rockchip_crtc_state { struct drm_crtc_state base; + int afbdc_win_format; + int afbdc_win_width; + int afbdc_win_height; + int afbdc_win_ptr; + int afbdc_win_id; + int afbdc_en; int output_type; int output_mode; }; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 834456f..6918223 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -99,6 +99,7 @@ struct vop_win { struct drm_plane base; const struct vop_win_data *data; struct vop *vop; + int id; /* protected by dev->event_lock */ bool enable; @@ -514,6 +515,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc) VOP_WIN_SET(vop, win, enable, 0); spin_unlock(&vop->reg_lock); } + VOP_CTRL_SET(vop, afbdc_en, 0); drm_crtc_vblank_off(crtc); @@ -1007,9 +1009,81 @@ static void vop_crtc_enable(struct drm_crtc *crtc) VOP_CTRL_SET(vop, standby, 0); } +static int vop_afbdc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state) +{ + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); + struct drm_atomic_state *state = crtc_state->state; + struct drm_plane *plane; + struct drm_plane_state *pstate; + struct vop_plane_state *plane_state; + struct vop_win *win; + int afbdc_format; + int i; + + s->afbdc_en = 0; + + for_each_plane_in_state(state, plane, pstate, i) { + struct drm_framebuffer *fb = pstate->fb; + struct drm_rect *src; + + win = to_vop_win(plane); + plane_state = to_vop_plane_state(pstate); + + if (pstate->crtc != crtc || !fb) + continue; + + if (fb->modifier[0] != DRM_FORMAT_MOD_ARM_AFBC) + continue; + + switch (plane_state->format) { + case VOP_FMT_ARGB8888: + afbdc_format = AFBDC_FMT_U8U8U8U8; + break; + case VOP_FMT_RGB888: + afbdc_format = AFBDC_FMT_U8U8U8; + break; + case VOP_FMT_RGB565: + afbdc_format = AFBDC_FMT_RGB565; + break; + default: + return -EINVAL; + } + + if (s->afbdc_en) { + DRM_ERROR("vop only support one afbc layer\n"); + return -EINVAL; + } + + src = &pstate->src; + if (src->x1 || src->y1 || fb->offsets[0]) { + DRM_ERROR("win[%d] afbdc not support offset display\n", + win->id); + DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n", + src->x1, src->y1, fb->offsets[0]); + return -EINVAL; + } + s->afbdc_win_format = afbdc_format; + s->afbdc_win_width = pstate->fb->width - 1; + s->afbdc_win_height = (drm_rect_height(src) >> 16) - 1; + s->afbdc_win_id = win->id; + s->afbdc_win_ptr = plane_state->yrgb_mst; + s->afbdc_en = 1; + } + + return 0; +} + +static int vop_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state) +{ + return vop_afbdc_atomic_check(crtc, crtc_state); +} + static void vop_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); struct vop *vop = to_vop(crtc); if (WARN_ON(!vop->is_enabled)) @@ -1017,6 +1091,19 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc, spin_lock(&vop->reg_lock); + if (s->afbdc_en) { + uint32_t pic_size; + + VOP_CTRL_SET(vop, afbdc_format, s->afbdc_win_format | 1 << 4); + VOP_CTRL_SET(vop, afbdc_hreg_block_split, 0); + VOP_CTRL_SET(vop, afbdc_sel, s->afbdc_win_id); + VOP_CTRL_SET(vop, afbdc_hdr_ptr, s->afbdc_win_ptr); + pic_size = (s->afbdc_win_width & 0xffff); + pic_size |= s->afbdc_win_height << 16; + VOP_CTRL_SET(vop, afbdc_pic_size, pic_size); + } + + VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en); vop_cfg_done(vop); spin_unlock(&vop->reg_lock); @@ -1042,6 +1129,7 @@ static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { .enable = vop_crtc_enable, .disable = vop_crtc_disable, .mode_fixup = vop_crtc_mode_fixup, + .atomic_check = vop_crtc_atomic_check, .atomic_flush = vop_crtc_atomic_flush, .atomic_begin = vop_crtc_atomic_begin, }; @@ -1413,6 +1501,7 @@ static void vop_win_init(struct vop *vop) struct vop_win *vop_win = &vop->win[i]; const struct vop_win_data *win_data = &vop_data->win[i]; + vop_win->id = i; vop_win->data = win_data; vop_win->vop = vop; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index ff4f52e..b9b120e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -15,6 +15,10 @@ #ifndef _ROCKCHIP_DRM_VOP_H #define _ROCKCHIP_DRM_VOP_H +#define AFBDC_FMT_RGB565 0x0 +#define AFBDC_FMT_U8U8U8U8 0x5 +#define AFBDC_FMT_U8U8U8 0x4 + enum vop_data_format { VOP_FMT_ARGB8888 = 0, VOP_FMT_RGB888, @@ -61,6 +65,15 @@ struct vop_ctrl { struct vop_reg hpost_st_end; struct vop_reg vpost_st_end; + /* AFBDC */ + struct vop_reg afbdc_en; + struct vop_reg afbdc_sel; + struct vop_reg afbdc_format; + struct vop_reg afbdc_hreg_block_split; + struct vop_reg afbdc_pic_size; + struct vop_reg afbdc_hdr_ptr; + struct vop_reg afbdc_rstn; + struct vop_reg cfg_done; }; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index f1a1688..a09437c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -300,6 +300,13 @@ static const struct vop_ctrl rk3399_ctrl_data = { .vact_st_end = VOP_REG(RK3399_DSP_VACT_ST_END, 0x1fff1fff, 0), .hpost_st_end = VOP_REG(RK3399_POST_DSP_HACT_INFO, 0x1fff1fff, 0), .vpost_st_end = VOP_REG(RK3399_POST_DSP_VACT_INFO, 0x1fff1fff, 0), + .afbdc_rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3), + .afbdc_en = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0), + .afbdc_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1), + .afbdc_format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16), + .afbdc_hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21), + .afbdc_hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0), + .afbdc_pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0), .cfg_done = VOP_REG_MASK(RK3399_REG_CFG_DONE, 0x1, 0), };