From patchwork Tue Mar 14 08:27:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 9622723 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 1A23260424 for ; Tue, 14 Mar 2017 08:28:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0757F2837F for ; Tue, 14 Mar 2017 08:28:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F08362850F; Tue, 14 Mar 2017 08:28:19 +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 64E892837F for ; Tue, 14 Mar 2017 08:28:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750861AbdCNI2S (ORCPT ); Tue, 14 Mar 2017 04:28:18 -0400 Received: from mailout3.w1.samsung.com ([210.118.77.13]:56136 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751020AbdCNI2Q (ORCPT ); Tue, 14 Mar 2017 04:28:16 -0400 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0OMS00GSNQ706H50@mailout3.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Tue, 14 Mar 2017 08:28:12 +0000 (GMT) Received: from eusmges1.samsung.com (unknown [203.254.199.239]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20170314082812eucas1p13ec103135bd2b79430663977dfd29744~rskCTXm7T2692826928eucas1p1p; Tue, 14 Mar 2017 08:28:12 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges1.samsung.com (EUCPMTA) with SMTP id 0C.5C.16908.E99A7C85; Tue, 14 Mar 2017 08:28:14 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20170314082811eucas1p108416d2ab30335f6644cec5d43c0b847~rskBefJH52537425374eucas1p1w; Tue, 14 Mar 2017 08:28:11 +0000 (GMT) X-AuditID: cbfec7ef-f79d26d00000420c-2f-58c7a99e7826 Received: from eusync1.samsung.com ( [203.254.199.211]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id C6.B9.10233.7A9A7C85; Tue, 14 Mar 2017 08:28:23 +0000 (GMT) Received: from AMDC2768.DIGITAL.local ([106.120.43.17]) by eusync1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0OMS00G2GQ6XHC40@eusync1.samsung.com>; Tue, 14 Mar 2017 08:28:11 +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 2/5] drm/exynos/decon5433: fix vblank event handling Date: Tue, 14 Mar 2017 09:27:57 +0100 Message-id: <1489480080-25633-3-git-send-email-a.hajda@samsung.com> X-Mailer: git-send-email 2.7.4 In-reply-to: <1489480080-25633-1-git-send-email-a.hajda@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrPIsWRmVeSWpSXmKPExsWy7djP87rzVh6PMHj9Xt3i1rpzrBYbZ6xn tbjy9T2bxaT7E1gs3rxdw2Rx/vwGdosZ5/cxWaw9cpfdgcNj06pONo/73ceZPLb032X36Nuy itHj8ya5ANYoLpuU1JzMstQifbsEroxZM7qYC+brVyzcfJWpgXGVWhcjJ4eEgInEkzfP2SFs MYkL99azdTFycQgJLGOUOHXhEROE85lRonf6fSaYjmu/n7LAVU1794QVwvnPKPH50wZWkCo2 AU2Jv5tvsoHYIgLKEqv2tbODFDELbGCSuDn7OSNIQljARWLN9qfMIDaLgKrEqYsLgJo5OHgF nCWe/C+A2CYncfNcJzNImBOo/M9pBZAxEgK/2STu7f8FFpcQkJXYdIAZotxF4uHxmywQtrDE q+NboF6Tkbg8uZsForebUeJT/wl2CGcKo8S/DzOguq0lDh+/CPYAswCfxKRt06EW8Ep0tAlB lHhITLhxixHCdpTY2NLLDPH8dEaJl6/OsUxglFnAyLCKUSS1tDg3PbXYUK84Mbe4NC9dLzk/ dxMjMJpP/zv+fgfj0+aQQ4wCHIxKPLwNc45FCLEmlhVX5h5ilOBgVhLh3dZ0PEKINyWxsiq1 KD++qDQntfgQozQHi5I4794FV8KFBNITS1KzU1MLUotgskwcnFINjEJFPa/lROez/eM1c7zj GREoLD/5pP+ENE/926vnSTauf7Dx+OVkT+ElR3oiQ0wWyTqYNU943aS263czz3yvvDVXZVcc bJrBKnP/6ezmd2wekrVu4oL/OrJeyP5g/CvKsS10avTUp73thb0fa9VPP8sVKM3Z7eEf8SFS g/GL+7Jv5t2lNmb3lViKMxINtZiLihMB5cFuleICAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrLLMWRmVeSWpSXmKPExsVy+t/xy7rLVx6PMGhvNrG4te4cq8XGGetZ La58fc9mMen+BBaLN2/XMFmcP7+B3WLG+X1MFmuP3GV34PDYtKqTzeN+93Emjy39d9k9+ras YvT4vEkugDXKzSYjNTEltUghNS85PyUzL91WKTTETddCSSEvMTfVVilC1zckSEmhLDGnFMgz MkADDs4B7sFK+nYJbhmzZnQxF8zXr1i4+SpTA+MqtS5GTg4JAROJa7+fskDYYhIX7q1n62Lk 4hASWMIoMW/DLiinkUni8K7NjCBVbAKaEn8332QDsUUElCVW7WtnByliFtjAJHG37yQrSEJY wEVizfanzCA2i4CqxKmLC4DiHBy8As4ST/4XQGyTk7h5rpMZJMwJVP7ntAJIWAioYt+tyWwT GHkXMDKsYhRJLS3OTc8tNtIrTswtLs1L10vOz93ECAzqbcd+btnB2PUu+BCjAAejEg9vw5xj EUKsiWXFlbmHGCU4mJVEeLc1HY8Q4k1JrKxKLcqPLyrNSS0+xGgKdNJEZinR5HxgxOWVxBua GJpbGhoZW1iYGxkpifNO/XAlXEggPbEkNTs1tSC1CKaPiYNTqoGx+vQku21XpV4ciJ9WsGcR 75n9Kn6Pj003cF8rzfGFia+B59yD8i1as0r8ciZ+eFCs7OvCtaLvxmP++Qrfprqkb26r3NIf 1+Tyuj/bc7um7p+4rzk6lR2WIWc1280u8nxpa9DTWWKwV9lLlfHRaT3Hq2Jd7jK5ORfs+w+q V4crL+W59bfqyCElluKMREMt5qLiRAAeOS69gAIAAA== X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20170314082811eucas1p108416d2ab30335f6644cec5d43c0b847 X-Msg-Generator: CA X-Sender-IP: 182.198.249.180 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: 20170314082811eucas1p108416d2ab30335f6644cec5d43c0b847 X-RootMTR: 20170314082811eucas1p108416d2ab30335f6644cec5d43c0b847 References: <1489480080-25633-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 --- v3: - handle wrap-around of frame counter 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 | 78 ++++++++++++++++++++++++++- include/video/exynos5433_decon.h | 8 +++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 2130ccf..cfe6f8a 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,24 @@ 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) { + /* handle only if incremented, take care of wrap-around */ + if ((s32)(frm - ctx->frame_id) > 0) + 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 +674,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 +747,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)