From patchwork Mon Mar 13 07:31:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 9619945 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 0800A60244 for ; Mon, 13 Mar 2017 07:32:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E8CFB28305 for ; Mon, 13 Mar 2017 07:32:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DB70D28343; Mon, 13 Mar 2017 07:32: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 D3E2028305 for ; Mon, 13 Mar 2017 07:32:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750902AbdCMHcR (ORCPT ); Mon, 13 Mar 2017 03:32:17 -0400 Received: from mailout3.w1.samsung.com ([210.118.77.13]:64940 "EHLO mailout3.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750848AbdCMHcQ (ORCPT ); Mon, 13 Mar 2017 03:32: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 <0OMQ00D8CSXOD740@mailout3.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Mon, 13 Mar 2017 07:32:12 +0000 (GMT) Received: from eusmges5.samsung.com (unknown [203.254.199.245]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20170313073211eucas1p2db1315b967bfd6f41e7ff7a9f50eeeec~rYJ2mUxXp1456414564eucas1p2N; Mon, 13 Mar 2017 07:32:11 +0000 (GMT) Received: from eucas1p1.samsung.com ( [182.198.249.206]) by eusmges5.samsung.com (EUCPMTA) with SMTP id 73.C1.17477.BFA46C85; Mon, 13 Mar 2017 07:32:11 +0000 (GMT) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eucas1p1.samsung.com (KnoxPortal) with ESMTP id 20170313073211eucas1p17a7cdf647b711343ef382adb792ed84e~rYJ17yz9V1535115351eucas1p1s; Mon, 13 Mar 2017 07:32:11 +0000 (GMT) X-AuditID: cbfec7f5-f79d06d000004445-64-58c64afb1fa3 Received: from eusync1.samsung.com ( [203.254.199.211]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id 7C.17.06687.F5B46C85; Mon, 13 Mar 2017 07:33:51 +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 <0OMQ00LJQSXKJS60@eusync1.samsung.com>; Mon, 13 Mar 2017 07:32:11 +0000 (GMT) From: Andrzej Hajda To: Inki Dae Cc: =?UTF-8?q?Michel=20D=C3=A4nzer?= , Andrzej Hajda , Bartlomiej Zolnierkiewicz , Marek Szyprowski , dri-devel@lists.freedesktop.org, linux-samsung-soc@vger.kernel.org, Krzysztof Kozlowski , Javier Martinez Canillas Subject: [PATCH v3 03/12] drm/exynos/decon5433: fix vblank event handling Date: Mon, 13 Mar 2017 08:31:47 +0100 Message-id: <1489390307-22816-1-git-send-email-a.hajda@samsung.com> X-Mailer: git-send-email 2.7.4 In-reply-to: <58C63D1F.3030701@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrFIsWRmVeSWpSXmKPExsWy7djPc7q/vY5FGLTf1bG4te4cq8XGGetZ La58fc9mMen+BBaLN2/XMFmcP7+B3WLG+X1MFmuP3GW3OH7iDasDp8fiBZvYPDat6mTzuN99 nMljS/9ddo++LasYPT5vkgtgi+KySUnNySxLLdK3S+DKuHB+MlvBfP2KCz9vsDcwrlLrYuTk kBAwkZg75zo7hC0mceHeerYuRi4OIYGljBJfVn5khXA+M0o0XXjODtPxa9t2JojEMkaJv58X MUI4/xklJs3tYQGpYhPQlPi7+SYbiC0ioCyxal87O0gRs8BLJoknK/+BFQkLeEq83tTJBGKz CKhKtLb1gTXwCjhLLOm6ArVOTuLmuU5mEJtTQFti+dp3YDdJCHSzS8ydPwVoEAeQIyux6QAz RL2LxPW3t5kgbGGJV8e3QM2RkejsOMgE1cso8an/BDuEM4VR4t+HGVDd1hKHj19kBbGZBfgk Jm2bzgyxgFeio00IosRDovPQW6gFjhIPDt4As4UE6iQ2Nn1hnsAos4CRYRWjSGppcW56arGp XnFibnFpXrpecn7uJkZgjJ/+d/zrDsalx6wOMQpwMCrx8G6YdTRCiDWxrLgy9xCjBAezkghv tuWxCCHelMTKqtSi/Pii0pzU4kOM0hwsSuK8exZcCRcSSE8sSc1OTS1ILYLJMnFwSjUwljPL Bxn8v1Fwvsvri7c3W+m5gpm1/1bdKWa/KD7Z5V9Es5pZjnZPg+A0FoX9P0Oi2jcyLeia02Ia kd3r/8dk146Jk33qV6jtl+aaVBihWifnlLvxVbT2756zX99v2KVttG7OCyujjW+y31+s4Sky 7nAv7Zx44qr1hzk2PufzmXzd3zjbn7ilxFKckWioxVxUnAgA9n5scu0CAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrBLMWRmVeSWpSXmKPExsVy+t/xy7rx3sciDG5ckbO4te4cq8XGGetZ La58fc9mMen+BBaLN2/XMFmcP7+B3WLG+X1MFmuP3GW3OH7iDasDp8fiBZvYPDat6mTzuN99 nMljS/9ddo++LasYPT5vkgtgi3KzyUhNTEktUkjNS85PycxLt1UKDXHTtVBSyEvMTbVVitD1 DQlSUihLzCkF8owM0ICDc4B7sJK+XYJbxoXzk9kK5utXXPh5g72BcZVaFyMnh4SAicSvbduZ IGwxiQv31rN1MXJxCAksYZRoenyaFSQhJNDIJHF/uwiIzSagKfF38002EFtEQFli1b52dpAG ZoGXTBITJ+1mAUkIC3hKvN7UCTaVRUBVorWtD6yBV8BZYknXFXaIbXISN891MoPYnALaEsvX voNapiWx8scBpgmMvAsYGVYxiqSWFuem5xYb6hUn5haX5qXrJefnbmIEhvq2Yz8372C8tDH4 EKMAB6MSDy/H3KMRQqyJZcWVuYcYJTiYlUR4sy2PRQjxpiRWVqUW5ccXleakFh9iNAU6aiKz lGhyPjAO80riDU0MzS0NjYwtLMyNjJTEeUs+XAkXEkhPLEnNTk0tSC2C6WPi4JRqYEz+LWC6 KvfF55f5KbMOumr5FD2YfKdr/+SpsQv2ZX4sVmG/+HK6/URn5/qH8hrl9bILNTM7z13YuGqS buF6iVdHYmvOBwrWh36dcLZ+v9vBHdsftZ825vefctB9n6WwYNyWupvfSmUbbuvX71yt6frP Yb8o97pb64J6mZ1W5y24t+T04sWiOvOUWIozEg21mIuKEwHjgMBqiwIAAA== X-MTR: 20000000000000000@CPGS X-CMS-MailID: 20170313073211eucas1p17a7cdf647b711343ef382adb792ed84e 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: 20170313073211eucas1p17a7cdf647b711343ef382adb792ed84e X-RootMTR: 20170313073211eucas1p17a7cdf647b711343ef382adb792ed84e References: <58C63D1F.3030701@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 147911e..73482d3 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)