From patchwork Mon Nov 30 13:53:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 7725751 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 414F8BEEE1 for ; Mon, 30 Nov 2015 13:54:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 402FD2042B for ; Mon, 30 Nov 2015 13:54:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 13D6520553 for ; Mon, 30 Nov 2015 13:54:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753983AbbK3NyB (ORCPT ); Mon, 30 Nov 2015 08:54:01 -0500 Received: from mailout3.w1.samsung.com ([210.118.77.13]:49874 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754271AbbK3Nx6 (ORCPT ); Mon, 30 Nov 2015 08:53:58 -0500 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NYM00AV1RXV8QB0@mailout3.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Mon, 30 Nov 2015 13:53:55 +0000 (GMT) X-AuditID: cbfec7f5-f79b16d000005389-fd-565c54f251e4 Received: from eusync2.samsung.com ( [203.254.199.212]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id 86.78.21385.2F45C565; Mon, 30 Nov 2015 13:53:54 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NYM007NRRXFE700@eusync2.samsung.com>; Mon, 30 Nov 2015 13:53:54 +0000 (GMT) From: Marek Szyprowski To: dri-devel@lists.freedesktop.org, linux-samsung-soc@vger.kernel.org Cc: Marek Szyprowski , Inki Dae , Joonyoung Shim , Seung-Woo Kim , Andrzej Hajda , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz , Tobias Jakobi , Gustavo Padovan , Javier Martinez Canillas Subject: [PATCH v2 19/22] drm/exynos: fix to calculate offset of each plane for ipp gsc Date: Mon, 30 Nov 2015 14:53:34 +0100 Message-id: <1448891617-18830-20-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1448891617-18830-1-git-send-email-m.szyprowski@samsung.com> References: <1448891617-18830-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrJLMWRmVeSWpSXmKPExsVy+t/xK7qfQmLCDF5OsbK4te4cq8XGGetZ La58fc9msfPBLnaLSfcnsFi8ebuGyeLFvYssFq9fGFrMOL+PyWLtkbvsFjMmv2SzaFv9gdVi 1a4/jA68Hjtn3WX3uN99nMnj3zF2jy39QN7OSXuZPPq2rGL0+LxJLoA9issmJTUnsyy1SN8u gStjRhdPwTnNig17vzA1MH5S7GLk5JAQMJFYu+EdK4QtJnHh3nq2LkYuDiGBpYwSp9qeMEM4 TUwS7y6sZAOpYhMwlOh62wVmiwi4STQdngnWzSxwmFni8NQ6EFtYIFLi05GNLCA2i4CqxJ3F V8HqeQU8JZ5v/sMIsU1O4v/LFUwgNidQ/MnZ0+wgtpCAh8SGGceYJjDyLmBkWMUomlqaXFCc lJ5rpFecmFtcmpeul5yfu4kREqBfdzAuPWZ1iFGAg1GJh1fCLDpMiDWxrLgy9xCjBAezkghv oGlMmBBvSmJlVWpRfnxRaU5q8SFGaQ4WJXHembvehwgJpCeWpGanphakFsFkmTg4pRoYneZt r9k01VFov7OLk9AWWQeDKWo9V3viXXJvm6t38MecvbXmR3ZbRIvY3BX71m6ZMMm7veNS4rWa xvuFp9+GqQfcTHgrPDdoUssM+x8FT7am7F+aoPdJ9sOdYL/i2Uyqc5Wc2q5Lt5jPn1jZ6Hq3 eVJVSZ+dxsyM2282ti94/chUYqXSWZ4fSizFGYmGWsxFxYkAheuc9kwCAAA= Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Seung-Woo Kim NV12 and YUV420 formats are needed to calculate offset of each plane in a gem buffer for ipp gsc. Without proper offset, only Y plane can be processed, so result shows green frame. This patch fixes to calculate offset for cbcr planes for NV12 and YUV420 formats. Signed-off-by: Seung-Woo Kim Signed-off-by: Marek Szyprowski --- drivers/gpu/drm/exynos/exynos_drm_gsc.c | 116 ++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 7aecd23cfa11..2882b9347cc8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -486,6 +486,98 @@ static void gsc_handle_irq(struct gsc_context *ctx, bool enable, gsc_write(cfg, GSC_IRQ); } +static int gsc_set_planar_addr(struct drm_exynos_ipp_buf_info *buf_info, + u32 fmt, struct drm_exynos_sz *sz) +{ + dma_addr_t *base[EXYNOS_DRM_PLANAR_MAX]; + uint64_t size[EXYNOS_DRM_PLANAR_MAX]; + uint64_t ofs[EXYNOS_DRM_PLANAR_MAX]; + bool bypass = false; + uint64_t tsize = 0; + int i; + + for_each_ipp_planar(i) { + base[i] = &buf_info->base[i]; + size[i] = buf_info->size[i]; + ofs[i] = 0; + tsize += size[i]; + DRM_DEBUG_KMS("base[%d][0x%lx]s[%d][%llu]\n", + i, (unsigned long)*base[i], i, size[i]); + } + + if (!tsize) { + DRM_INFO("failed to get buffer size.\n"); + return 0; + } + + switch (fmt) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + ofs[0] = sz->hsize * sz->vsize; + ofs[1] = ofs[0] >> 1; + if (*base[0] && *base[1]) { + if (size[0] + size[1] < ofs[0] + ofs[1]) + goto err_info; + bypass = true; + } + break; + case DRM_FORMAT_YUV410: + case DRM_FORMAT_YVU410: + case DRM_FORMAT_YUV411: + case DRM_FORMAT_YVU411: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: + ofs[0] = sz->hsize * sz->vsize; + ofs[1] = ofs[2] = ofs[0] >> 2; + if (*base[0] && *base[1] && *base[2]) { + if (size[0]+size[1]+size[2] < ofs[0]+ofs[1]+ofs[2]) + goto err_info; + bypass = true; + } + break; + case DRM_FORMAT_XRGB8888: + ofs[0] = sz->hsize * sz->vsize << 2; + if (*base[0]) { + if (size[0] < ofs[0]) + goto err_info; + } + bypass = true; + break; + default: + bypass = true; + break; + } + + if (!bypass) { + *base[1] = *base[0] + ofs[0]; + if (ofs[1] && ofs[2]) + *base[2] = *base[1] + ofs[1]; + } + + DRM_DEBUG_KMS("y[0x%lx],cb[0x%lx],cr[0x%lx]\n", (unsigned long)*base[0], + (unsigned long)*base[1], (unsigned long)*base[2]); + + return 0; + +err_info: + DRM_ERROR("invalid size for fmt[0x%x]\n", fmt); + + for_each_ipp_planar(i) { + base[i] = &buf_info->base[i]; + size[i] = buf_info->size[i]; + + DRM_ERROR("base[%d][0x%lx]s[%d][%llu]ofs[%d][%llu]\n", + i, (unsigned long)*base[i], i, size[i], i, ofs[i]); + } + + return -EINVAL; +} static int gsc_src_set_fmt(struct device *dev, u32 fmt) { @@ -715,6 +807,8 @@ static int gsc_src_set_addr(struct device *dev, struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; struct drm_exynos_ipp_property *property; + struct drm_exynos_ipp_config *config; + int ret; if (!c_node) { DRM_ERROR("failed to get c_node.\n"); @@ -734,6 +828,13 @@ static int gsc_src_set_addr(struct device *dev, /* address register set */ switch (buf_type) { case IPP_BUF_ENQUEUE: + config = &property->config[EXYNOS_DRM_OPS_SRC]; + ret = gsc_set_planar_addr(buf_info, config->fmt, &config->sz); + if (ret) { + dev_err(dev, "failed to set plane src addr.\n"); + return ret; + } + gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], GSC_IN_BASE_ADDR_Y(buf_id)); gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], @@ -1170,6 +1271,8 @@ static int gsc_dst_set_addr(struct device *dev, struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; struct drm_exynos_ipp_property *property; + struct drm_exynos_ipp_config *config; + int ret; if (!c_node) { DRM_ERROR("failed to get c_node.\n"); @@ -1189,6 +1292,13 @@ static int gsc_dst_set_addr(struct device *dev, /* address register set */ switch (buf_type) { case IPP_BUF_ENQUEUE: + config = &property->config[EXYNOS_DRM_OPS_DST]; + ret = gsc_set_planar_addr(buf_info, config->fmt, &config->sz); + if (ret) { + dev_err(dev, "failed to set plane dst addr.\n"); + return ret; + } + gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y], GSC_OUT_BASE_ADDR_Y(buf_id)); gsc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB], @@ -1320,6 +1430,12 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id) return IRQ_NONE; } + if (c_node->state == IPP_STATE_STOP) { + DRM_ERROR("invalid state: prop_id[%d]\n", + c_node->property.prop_id); + return IRQ_HANDLED; + } + if (status & GSC_IRQ_STATUS_OR_FRM_DONE) { dev_dbg(ippdrv->dev, "occurred frame done at %d, status 0x%x.\n", ctx->id, status);