From patchwork Wed Mar 8 14:58:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 9611405 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 0DEF9604DD for ; Wed, 8 Mar 2017 15:10:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BE64D285DE for ; Wed, 8 Mar 2017 15:10:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B351D285ED; Wed, 8 Mar 2017 15:10:17 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 248F8285E3 for ; Wed, 8 Mar 2017 15:10:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752110AbdCHPKQ (ORCPT ); Wed, 8 Mar 2017 10:10:16 -0500 Received: from mailout2.w1.samsung.com ([210.118.77.12]:63767 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750728AbdCHPKN (ORCPT ); Wed, 8 Mar 2017 10:10:13 -0500 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0OMI007VN4AFUO90@mailout2.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Wed, 08 Mar 2017 14:59:03 +0000 (GMT) Received: from eusmges2.samsung.com (unknown [203.254.199.241]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20170308145902eucas1p1ae75a1703d9bb04a7c7c209fd21da30a~p8Bk3lExM0116901169eucas1p1k; Wed, 8 Mar 2017 14:59:02 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges2.samsung.com (EUCPMTA) with SMTP id 2F.BB.30614.63C10C85; Wed, 8 Mar 2017 14:59:02 +0000 (GMT) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20170308145902eucas1p24636df9b8eafd2b07f12a2c700c6bcea~p8BkDms8S2378523785eucas1p2F; Wed, 8 Mar 2017 14:59:02 +0000 (GMT) X-AuditID: cbfec7f1-f793f6d000007796-5a-58c01c3632a1 Received: from eusync3.samsung.com ( [203.254.199.213]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id 02.F4.06687.69C10C85; Wed, 8 Mar 2017 15:00:38 +0000 (GMT) Received: from AMDC2768.DIGITAL.local ([106.120.43.17]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OMI0059P4AC5T30@eusync3.samsung.com>; Wed, 08 Mar 2017 14:59:01 +0000 (GMT) From: Andrzej Hajda To: Inki Dae Cc: Andrzej Hajda , Bartlomiej Zolnierkiewicz , Marek Szyprowski , dri-devel@lists.freedesktop.org, linux-samsung-soc@vger.kernel.org, Krzysztof Kozlowski , Javier Martinez Canillas Subject: [PATCH v2 03/12] drm/exynos/decon5433: fix vblank event handling Date: Wed, 08 Mar 2017 15:58:37 +0100 Message-id: <1488985126-25288-4-git-send-email-a.hajda@samsung.com> X-Mailer: git-send-email 2.7.4 In-reply-to: <1488985126-25288-1-git-send-email-a.hajda@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrAIsWRmVeSWpSXmKPExsWy7djPc7pmMgciDNZv07C4te4cq8XGGetZ La58fc9mMen+BBaLN2/XMFmcP7+B3WLG+X1MFmuP3GV34PDYtKqTzeN+93Emjy39d9k9+ras YvT4vEkugDWKyyYlNSezLLVI3y6BK+PKg9vMBcv1KpqWbGVqYDyj2sXIySEhYCKxqHM9I4Qt JnHh3nq2LkYuDiGBpYwSa9bMZYZwPjNKvDg7FaiKA6zjRHsFRHwZo8SjW9eZIJz/jBI9kxaC jWIT0JT4u/kmG4gtIqAssWpfOztIEbPABiaJm7OfgxUJC3hK3L18jAXEZhFQldj3posZxOYV cJaY8vEUC8RNchI3z3WCxTkFXCT6Pk4GO0lC4DebxJZjE9ggTpKV2HSAGaLeRaJrxgOof4Ql Xh3fwg5hy0h0dhxkgujtZpT41H+CHcKZwijx78MMqG5ricPHL7KC2MwCfBKTtk1nhljAK9HR JgRR4iFxtucN1FBHiS+PPjBCvD+dUaL5WzvzBEaZBYwMqxhFUkuLc9NTi430ihNzi0vz0vWS 83M3MQLj+fS/4x93ML4/YXWIUYCDUYmHV0D4QIQQa2JZcWXuIUYJDmYlEd4LX/dHCPGmJFZW pRblxxeV5qQWH2KU5mBREufds+BKuJBAemJJanZqakFqEUyWiYNTqoFR81H2lWCeA/6KLXor Ln9Ykz1Vqmf5amPe2Ze272Xmt58evCxbsz4wKqH2z6PX8SaOJ6rUA23SZ63izbJv/p2yyvDT pLwVS5U6d5p2beq+c2Hqy4WuHw8teLpNm/Uw6+u5aZO+fe3Wndo0cy3zr2k++nO2s7Ns8jq6 VV1x31L3RE+/bW/z1HgfK7EUZyQaajEXFScCAKPFxMHjAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrLLMWRmVeSWpSXmKPExsVy+t/xq7rTZA5EGHx4p25xa905VouNM9az Wlz5+p7NYtL9CSwWb96uYbI4f34Du8WM8/uYLNYeucvuwOGxaVUnm8f97uNMHlv677J79G1Z xejxeZNcAGuUm01GamJKapFCal5yfkpmXrqtUmiIm66FkkJeYm6qrVKErm9IkJJCWWJOKZBn ZIAGHJwD3IOV9O0S3DKuPLjNXLBcr6JpyVamBsYzql2MHBwSAiYSJ9oruhg5gUwxiQv31rN1 MXJxCAksYZS4sHQqK4TTyCTx6/ZOVpAqNgFNib+bb7KB2CICyhKr9rWzgxQxC2xgkrjbdxKs SFjAU+Lu5WMsIDaLgKrEvjddzCA2r4CzxJSPp1gg1slJ3DzXCRbnFHCR6Ps4mRnkIiGgmqX9 OhMYeRcwMqxiFEktLc5Nzy021CtOzC0uzUvXS87P3cQIDOptx35u3sF4aWPwIUYBDkYlHl4B 4QMRQqyJZcWVuYcYJTiYlUR4L3zdHyHEm5JYWZValB9fVJqTWnyI0RToponMUqLJ+cCIyyuJ NzQxNLc0NDK2sDA3MlIS5y35cCVcSCA9sSQ1OzW1ILUIpo+Jg1OqgTHthpZ3g6XU7OMb+6P/ 7/jcmyH0limSY/qJsJCiN+riU6w906oWcoa9KjzuO0ejRV4omPWqVIEXX7PlRzdWLZnDv0/X RZgHintUXS7Lip+66eSmd1WqR+buNvm67+LGsE2/HrtmVE5fHXUvgFtpQe6fQq+d0sFOi/I/ lO89l64pJGL3rdlnuRJLcUaioRZzUXEiANYOIsOAAgAA X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20170308145902eucas1p24636df9b8eafd2b07f12a2c700c6bcea X-Msg-Generator: CA X-Sender-IP: 182.198.249.179 X-Local-Sender: =?UTF-8?B?QW5kcnplaiBIYWpkYRtTUlBPTC1LZXJuZWwgKFRQKRvsgrw=?= =?UTF-8?B?7ISx7KCE7J6QG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Global-Sender: =?UTF-8?B?QW5kcnplaiBIYWpkYRtTUlBPTC1LZXJuZWwgKFRQKRtTYW1z?= =?UTF-8?B?dW5nIEVsZWN0cm9uaWNzG1NlbmlvciBTb2Z0d2FyZSBFbmdpbmVlcg==?= X-Sender-Code: =?UTF-8?B?QzEwG0VIURtDMTBDRDAyQ0QwMjczOTI=?= CMS-TYPE: 201P X-HopCount: 7 X-CMS-RootMailID: 20170308145902eucas1p24636df9b8eafd2b07f12a2c700c6bcea X-RootMTR: 20170308145902eucas1p24636df9b8eafd2b07f12a2c700c6bcea References: <1488985126-25288-1-git-send-email-a.hajda@samsung.com> Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Current implementation of event handling assumes that vblank interrupt is always called at the right time. It is not true, it can be delayed due to various reasons. As a result different races can happen. The patch fixes the issue by using hardware frame counter present in DECON to serialize vblank and commit completion events. Signed-off-by: Andrzej Hajda --- v2: - added internal decon_get_frame_count function, - updated frame counter on flush, - misc style fixes (thank Inki) --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 77 ++++++++++++++++++++++++++- include/video/exynos5433_decon.h | 8 +++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 147911e..4ca3d6e 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -68,6 +68,8 @@ struct decon_context { unsigned long flags; unsigned long out_type; int first_win; + spinlock_t vblank_lock; + u32 frame_id; }; static const uint32_t decon_formats[] = { @@ -122,6 +124,48 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc) writel(0, ctx->addr + DECON_VIDINTCON0); } +/* return number of starts/ends of frame transmissions since reset */ +static u32 decon_get_frame_count(struct decon_context *ctx, bool end) +{ + u32 frm, pfrm, status, cnt = 2; + + /* To get consistent result repeat read until frame id is stable. + * Usually the loop will be executed once, in rare cases when the loop + * is executed at frame change time 2nd pass will be needed. + */ + frm = readl(ctx->addr + DECON_CRFMID); + do { + status = readl(ctx->addr + DECON_VIDCON1); + pfrm = frm; + frm = readl(ctx->addr + DECON_CRFMID); + } while (frm != pfrm && --cnt); + + /* CRFMID is incremented on BPORCH in case of I80 and on VSYNC in case + * of RGB, it should be taken into account. + */ + if (!frm) + return 0; + + switch (status & (VIDCON1_VSTATUS_MASK | VIDCON1_I80_ACTIVE)) { + case VIDCON1_VSTATUS_VS: + if (!(ctx->out_type & IFTYPE_I80)) + --frm; + break; + case VIDCON1_VSTATUS_BP: + --frm; + break; + case VIDCON1_I80_ACTIVE: + case VIDCON1_VSTATUS_AC: + if (end) + --frm; + break; + default: + break; + } + + return frm; +} + static void decon_setup_trigger(struct decon_context *ctx) { if (!(ctx->out_type & (IFTYPE_I80 | I80_HW_TRG))) @@ -365,11 +409,14 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc, static void decon_atomic_flush(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; + unsigned long flags; int i; if (test_bit(BIT_SUSPENDED, &ctx->flags)) return; + spin_lock_irqsave(&ctx->vblank_lock, flags); + for (i = ctx->first_win; i < WINDOWS_NR; i++) decon_shadow_protect_win(ctx, i, false); @@ -378,12 +425,18 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc) if (ctx->out_type & IFTYPE_I80) set_bit(BIT_WIN_UPDATED, &ctx->flags); + + ctx->frame_id = decon_get_frame_count(ctx, true); + exynos_crtc_handle_event(crtc); + + spin_unlock_irqrestore(&ctx->vblank_lock, flags); } static void decon_swreset(struct decon_context *ctx) { unsigned int tries; + unsigned long flags; writel(0, ctx->addr + DECON_VIDCON0); for (tries = 2000; tries; --tries) { @@ -401,6 +454,10 @@ static void decon_swreset(struct decon_context *ctx) WARN(tries == 0, "failed to software reset DECON\n"); + spin_lock_irqsave(&ctx->vblank_lock, flags); + ctx->frame_id = 0; + spin_unlock_irqrestore(&ctx->vblank_lock, flags); + if (!(ctx->out_type & IFTYPE_HDMI)) return; @@ -579,6 +636,23 @@ static const struct component_ops decon_component_ops = { .unbind = decon_unbind, }; +static void decon_handle_vblank(struct decon_context *ctx) +{ + u32 frm; + + spin_lock(&ctx->vblank_lock); + + frm = decon_get_frame_count(ctx, true); + + if (frm != ctx->frame_id) { + if (frm > ctx->frame_id) + drm_crtc_handle_vblank(&ctx->crtc->base); + ctx->frame_id = frm; + } + + spin_unlock(&ctx->vblank_lock); +} + static irqreturn_t decon_irq_handler(int irq, void *dev_id) { struct decon_context *ctx = dev_id; @@ -599,7 +673,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id) (VIDOUT_INTERLACE_EN_F | VIDOUT_INTERLACE_FIELD_F)) return IRQ_HANDLED; } - drm_crtc_handle_vblank(&ctx->crtc->base); + decon_handle_vblank(ctx); } out: @@ -672,6 +746,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev) __set_bit(BIT_SUSPENDED, &ctx->flags); ctx->dev = dev; ctx->out_type = (unsigned long)of_device_get_match_data(dev); + spin_lock_init(&ctx->vblank_lock); if (ctx->out_type & IFTYPE_HDMI) { ctx->first_win = 1; diff --git a/include/video/exynos5433_decon.h b/include/video/exynos5433_decon.h index ef8e2a8..352fc0d 100644 --- a/include/video/exynos5433_decon.h +++ b/include/video/exynos5433_decon.h @@ -46,6 +46,7 @@ #define DECON_FRAMEFIFO_STATUS 0x0524 #define DECON_CMU 0x1404 #define DECON_UPDATE 0x1410 +#define DECON_CRFMID 0x1414 #define DECON_UPDATE_SCHEME 0x1438 #define DECON_VIDCON1 0x2000 #define DECON_VIDCON2 0x2004 @@ -142,6 +143,13 @@ #define STANDALONE_UPDATE_F (1 << 0) /* DECON_VIDCON1 */ +#define VIDCON1_LINECNT_MASK (0x0fff << 16) +#define VIDCON1_I80_ACTIVE (1 << 15) +#define VIDCON1_VSTATUS_MASK (0x3 << 13) +#define VIDCON1_VSTATUS_VS (0 << 13) +#define VIDCON1_VSTATUS_BP (1 << 13) +#define VIDCON1_VSTATUS_AC (2 << 13) +#define VIDCON1_VSTATUS_FP (3 << 13) #define VIDCON1_VCLK_MASK (0x3 << 9) #define VIDCON1_VCLK_RUN_VDEN_DISABLE (0x3 << 9) #define VIDCON1_VCLK_HOLD (0x0 << 9)