From patchwork Tue Nov 10 13:23:23 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 7590691 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 1FA4B9F392 for ; Tue, 10 Nov 2015 13:25:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D73BD207BA for ; Tue, 10 Nov 2015 13:25:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8D386207BE for ; Tue, 10 Nov 2015 13:25:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753108AbbKJNYy (ORCPT ); Tue, 10 Nov 2015 08:24:54 -0500 Received: from mailout3.w1.samsung.com ([210.118.77.13]:17246 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753101AbbKJNYx (ORCPT ); Tue, 10 Nov 2015 08:24:53 -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 <0NXL00KKWP9EYKA0@mailout3.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Tue, 10 Nov 2015 13:24:50 +0000 (GMT) X-AuditID: cbfec7f5-f794b6d000001495-26-5641f021dd77 Received: from eusync1.samsung.com ( [203.254.199.211]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id 9E.A8.05269.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 07/25] drm/exynos: fix to calculate offset of each plane for ipp gsc Date: Tue, 10 Nov 2015 14:23:23 +0100 Message-id: <1447161821-1877-8-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/xy7qKHxzDDCYfsba4te4cq8XGGetZ La58fc9msfPBLnaLSfcnsFi8ebuGyeLFvYssFq9fGFrMOL+PyWLtkbvsFjMmv2SzaFv9gdVi 1a4/jA68Hjtn3WX3uN99nMnj3zF2jy39QN7OSXuZPPq2rGL0+LxJLoA9issmJTUnsyy1SN8u gStjRhdPwTnNig17vzA1MH5S7GLk5JAQMJG48LSZBcIWk7hwbz1bFyMXh5DAUkaJpY0HGSGc JiaJg28fs4JUsQkYSnS97WIDsUUE3CSaDs8EizMLHGaWODy1DsQWFgiT+N13jxnEZhFQlXg2 oQ/M5hVwlzjWcRdqm5zE/5crmEBsTgEPia0fP4PVCAHV3Gy6yDKBkXcBI8MqRtHU0uSC4qT0 XCO94sTc4tK8dL3k/NxNjJAA/bqDcekxq0OMAhyMSjy8E745hAmxJpYVV+YeYpTgYFYS4WV8 7RgmxJuSWFmVWpQfX1Sak1p8iFGag0VJnHfmrvchQgLpiSWp2ampBalFMFkmDk6pBkYRnZhk 9r0V/x+xGTatMGFPNjBv3y9pdP3Sz49rp17On3jqiOjTmy1Wv93maTkvP3+pNiZOZk30CYX+ APHFisvOnb/lmH23agafRoS3mvaka63MTbaxslNnzn+gz/dO7++Jw1lmG31eNb6wPLVPQe7M +cjfE79tyK//cui4pqd/15mltXfMDyorsRRnJBpqMRcVJwIAyneJxEwCAAA= 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 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);