From patchwork Tue Nov 10 13:23:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 7590591 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id F1C4C9F392 for ; Tue, 10 Nov 2015 13:24:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D6D31207AA for ; Tue, 10 Nov 2015 13:24:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id ADBE7207B0 for ; Tue, 10 Nov 2015 13:24:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753082AbbKJNYw (ORCPT ); Tue, 10 Nov 2015 08:24:52 -0500 Received: from mailout1.w1.samsung.com ([210.118.77.11]:64203 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753094AbbKJNYv (ORCPT ); Tue, 10 Nov 2015 08:24:51 -0500 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout1.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NXL00BIFP9DC0A0@mailout1.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Tue, 10 Nov 2015 13:24:49 +0000 (GMT) X-AuditID: cbfec7f4-f79c56d0000012ee-5c-5641f021cd4e Received: from eusync1.samsung.com ( [203.254.199.211]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id A4.23.04846.120F1465; Tue, 10 Nov 2015 13:24:49 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NXL00L9RP94NP10@eusync1.samsung.com>; Tue, 10 Nov 2015 13:24:49 +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 06/25] drm/exynos: fix to calculate offset of each plane for ipp fimc Date: Tue, 10 Nov 2015 14:23:22 +0100 Message-id: <1447161821-1877-7-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1447161821-1877-1-git-send-email-m.szyprowski@samsung.com> References: <1447161821-1877-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrJLMWRmVeSWpSXmKPExsVy+t/xy7qKHxzDDD7PkrC4te4cq8XGGetZ La58fc9msfPBLnaLSfcnsFi8ebuGyeLFvYssFq9fGFrMOL+PyWLtkbvsFjMmv2SzaFv9gdVi 1a4/jA68Hjtn3WX3uN99nMnj3zF2jy39QN7OSXuZPPq2rGL0+LxJLoA9issmJTUnsyy1SN8u gSvjS993toLVphVd01cxNjBu1e5i5OSQEDCRuPXuGRuELSZx4d56MFtIYCmjxM27nF2MXEB2 E5PEwbePWUESbAKGEl1vu8CKRATcJJoOzwSLMwscZpY4PLUOxBYWCJe4s3UtWA2LgKpE96pm sBpeAXeJjtPL2CGWyUn8f7mCCcTmFPCQ2PrxMzPEYneJm00XWSYw8i5gZFjFKJpamlxQnJSe a6hXnJhbXJqXrpecn7uJERKgX3YwLj5mdYhRgINRiYd3wjeHMCHWxLLiytxDjBIczEoivIyv HcOEeFMSK6tSi/Lji0pzUosPMUpzsCiJ887d9T5ESCA9sSQ1OzW1ILUIJsvEwSnVwFhp6RPD +9p/399p/9Tc1KOz451nSgfO23Vz/hejTSmfTi69Ji9Sn+0bdcx2a93EV/vUVecsDbjMd+TF kS87YhpPXbTUP3L6yUlns5hfvwpT3X/XtogcLomfV6Jh6HS+XHel0d/66Q/3pXIsOx7ttVP3 jVyErduGRT3n8mb1m9zdKLJ8wuV/H7mUWIozEg21mIuKEwFTyGCoTAIAAA== 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=-7.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 need to calculate offset of each plane for ipp fimc in a gem buffer. 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_fimc.c | 106 +++++++++++++++++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_ipp.c | 15 ++++- drivers/gpu/drm/exynos/exynos_drm_ipp.h | 2 + 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index c747824f3c98..72a7ca188be5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -403,6 +403,97 @@ static void fimc_handle_lastend(struct fimc_context *ctx, bool enable) fimc_write(ctx, cfg, EXYNOS_CIOCTRL); } +static int fimc_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]; + } + + if (!tsize) { + DRM_INFO("%s:failed to get buffer size.\n", __func__); + 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: + case DRM_FORMAT_ARGB8888: + 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("%s:y[0x%x],cb[0x%x],cr[0x%x]\n", __func__, + *base[0], *base[1], *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("buf[%d] - base[0x%x] sz[%llu] ofs[%llu]\n", + i, *base[i], size[i], ofs[i]); + } + + return -EINVAL; +} static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt) { @@ -689,6 +780,7 @@ static int fimc_src_set_addr(struct device *dev, 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"); @@ -709,6 +801,12 @@ static int fimc_src_set_addr(struct device *dev, switch (buf_type) { case IPP_BUF_ENQUEUE: config = &property->config[EXYNOS_DRM_OPS_SRC]; + ret = fimc_set_planar_addr(buf_info, config->fmt, &config->sz); + if (ret) { + dev_err(dev, "failed to set plane src addr.\n"); + return ret; + } + fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y], EXYNOS_CIIYSA0); @@ -1148,6 +1246,7 @@ static int fimc_dst_set_addr(struct device *dev, 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"); @@ -1168,6 +1267,11 @@ static int fimc_dst_set_addr(struct device *dev, switch (buf_type) { case IPP_BUF_ENQUEUE: config = &property->config[EXYNOS_DRM_OPS_DST]; + ret = fimc_set_planar_addr(buf_info, config->fmt, &config->sz); + if (ret) { + dev_err(dev, "failed to set plane dst addr.\n"); + return ret; + } fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y], EXYNOS_CIOYSA(buf_id)); @@ -1562,6 +1666,8 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd) /* reset sequence */ fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ); + fimc_clear_addr(ctx); + /* Scaler disable */ fimc_clear_bits(ctx, EXYNOS_CISCCTRL, EXYNOS_CISCCTRL_SCALERSTART); diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 67d24236e745..408a14a9a180 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -571,6 +571,7 @@ static struct drm_exynos_ipp_mem_node /* get dma address by handle */ if (qbuf->handle[i]) { dma_addr_t *addr; + unsigned long size; addr = exynos_drm_gem_get_dma_addr(drm_dev, qbuf->handle[i], c_node->filp); @@ -580,10 +581,20 @@ static struct drm_exynos_ipp_mem_node return ERR_PTR(-EFAULT); } + size = exynos_drm_gem_get_size(drm_dev, + qbuf->handle[i], c_node->filp); + if (!size) { + DRM_ERROR("failed to get size.\n"); + ipp_put_mem_node(drm_dev, c_node, m_node); + return ERR_PTR(-EFAULT); + } + buf_info->handles[i] = qbuf->handle[i]; buf_info->base[i] = *addr; - DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%lx]\n", i, - buf_info->base[i], buf_info->handles[i]); + buf_info->size[i] = (uint64_t)size; + DRM_DEBUG_KMS("i[%d]base[%pad]hd[0x%lx]sz[%llx]\n", i, + &buf_info->base[i], buf_info->handles[i], + buf_info->size[i]); } } diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h index 2a61547a39d0..d4f0b588220b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h @@ -85,10 +85,12 @@ struct drm_exynos_ipp_cmd_node { * * @handles: Y, Cb, Cr each gem object handle. * @base: Y, Cb, Cr each planar address. + * @size: Y, Cb, Cr each planar size. */ struct drm_exynos_ipp_buf_info { unsigned long handles[EXYNOS_DRM_PLANAR_MAX]; dma_addr_t base[EXYNOS_DRM_PLANAR_MAX]; + uint64_t size[EXYNOS_DRM_PLANAR_MAX]; }; /*