From patchwork Fri Feb 16 11:25:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jyri Sarha X-Patchwork-Id: 128547 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp453916ljc; Fri, 16 Feb 2018 03:26:01 -0800 (PST) X-Google-Smtp-Source: AH8x226ka8IhkIyNL8WHtGcJMHVyLYT6uE7pzmg5BFHLMoBeBbtFWPXCP335ZEaqdsgh5KH+Czmf X-Received: by 2002:a17:902:a588:: with SMTP id az8-v6mr5734416plb.10.1518780361087; Fri, 16 Feb 2018 03:26:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518780361; cv=none; d=google.com; s=arc-20160816; b=UV0M6ccllePA9gu9hghVVfFpHjFMu7p8tAopQwig+HGLmC5puw0znJ2hDbqIpofloR bSx7xF7wxV6JkjqbP6bYXoub5E3+AMsePP0VrPUHCwvm3HProrrCuuLaxWOByv8GE9v2 owx6t1gqxu/If9fCcAl954bfpP27Eg3uaLfv31JvnkPMyqEs4pkJe3/6J585Xx+JsSjB m/bLdtNTCJMv2xTBlrhX2xDOzyZxjUtCmYdBwW4m+hknhhviy1UM7cNI8hFjPv4FIpRk YHMxUewn6gf0cQqhAlNUS2rAmfK0Grvyy9KVRv51awnOKj8GaTrx35PtH+fEC/bNqbgT VHmg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:mime-version:references:in-reply-to:message-id:date :subject:to:from:dkim-signature:delivered-to :arc-authentication-results; bh=2U1pHrgH59mTpLZRwNV7CcQMtU31TyfkfQyWg3r/8H4=; b=AhE4Od7zSfKBQO78gdYGjc402psamSsmAKseAmplxU4Fb8ZJQDcEYGS79sif3O1n0J EyKeMHI4PkiGJOgxisYPZmKPHd4yXBxm6lFdj8SzLFDHRLWFfgH4qPkB28ta3IrzDB9H hqYo1q9YZpouEsZyxnKb0garvWQDvZt18RKeRoM8/WQ7NSKUE/xWrs90uKwyjBnn0+aH zNsmdb3hSk8+67xX5M/490VKS1A0A/rImcrki/yJtjRZiRFAQ64Xc5EIIOEMbXOHpvVO cleQt2R7DwySX4d+EMqXNbEbgQ1a9vBlTsfTkVAvxIKaOQKtKYTl8JuReo/X4C8eWFfK zCRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@ti.com header.s=ti-com-17Q1 header.b=g8bfpNvD; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [131.252.210.177]) by mx.google.com with ESMTPS id y184si2657376pgd.291.2018.02.16.03.26.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 16 Feb 2018 03:26:01 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) client-ip=131.252.210.177; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@ti.com header.s=ti-com-17Q1 header.b=g8bfpNvD; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id ECBBA6E615; Fri, 16 Feb 2018 11:25:42 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from fllnx210.ext.ti.com (fllnx210.ext.ti.com [198.47.19.17]) by gabe.freedesktop.org (Postfix) with ESMTPS id D738E6E606 for ; Fri, 16 Feb 2018 11:25:22 +0000 (UTC) Received: from dflxv15.itg.ti.com ([128.247.5.124]) by fllnx210.ext.ti.com (8.15.1/8.15.1) with ESMTP id w1GBPKus025114; Fri, 16 Feb 2018 05:25:20 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ti.com; s=ti-com-17Q1; t=1518780320; bh=HY56uOeY/wBnNK5vS78QDuoZtrb6BmPsGjXJkxOFn+Y=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=g8bfpNvD/XIU3lPv1Q2yPcMSJNFiZUdC9Hp/P2o1FUA1UCmj7Rdb0T81o3RqsvktV 7ARRzMtiw71+jmid6ZczEDX53N2iURL06tvzK+9AZPKwPbqNn/ZibNW06uXxK0u1/+ LOe9uJglKsmQJ9bvr4C/W2isJO/NNrbM+NIOhQhs= Received: from DLEE113.ent.ti.com (dlee113.ent.ti.com [157.170.170.24]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id w1GBPKZ8003499; Fri, 16 Feb 2018 05:25:20 -0600 Received: from DLEE105.ent.ti.com (157.170.170.35) by DLEE113.ent.ti.com (157.170.170.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1261.35; Fri, 16 Feb 2018 05:25:19 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DLEE105.ent.ti.com (157.170.170.35) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1261.35 via Frontend Transport; Fri, 16 Feb 2018 05:25:20 -0600 Received: from jadmar.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id w1GBPCig028841; Fri, 16 Feb 2018 05:25:18 -0600 From: Jyri Sarha To: , , Subject: [PATCH RFC 4/9] drm/omap: Make omapdss API more generic Date: Fri, 16 Feb 2018 13:25:05 +0200 Message-ID: X-Mailer: git-send-email 2.7.4 In-Reply-To: References: MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jyri Sarha Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The new omapdss API is HW independent and cleans up some of the DSS5 specific hacks from the omapdrm side and gets rid off the DSS5 IRQ register bits and replace them with HW independent generic u64 based macros. The new macros make it more straight forward to implement the IRQ code for the future DSS versions that do not share the same register structure as DSS2 to DSS5 has. Signed-off-by: Jyri Sarha --- drivers/gpu/drm/omapdrm/dss/dispc.c | 115 +++++++++++++++++++++++++--------- drivers/gpu/drm/omapdrm/dss/dispc.h | 33 ++++++++++ drivers/gpu/drm/omapdrm/dss/omapdss.h | 80 +++++++++++------------ drivers/gpu/drm/omapdrm/omap_crtc.c | 19 +++--- drivers/gpu/drm/omapdrm/omap_crtc.h | 2 +- drivers/gpu/drm/omapdrm/omap_drv.h | 3 +- drivers/gpu/drm/omapdrm/omap_irq.c | 102 ++++++++++++------------------ drivers/gpu/drm/omapdrm/omap_irq.h | 2 +- drivers/gpu/drm/omapdrm/omap_plane.c | 7 +++ drivers/gpu/drm/omapdrm/omap_plane.h | 1 + 10 files changed, 219 insertions(+), 145 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 6f83b3e..3df0a88 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -714,30 +714,11 @@ static const char *dispc_mgr_name(struct dispc_device *dispc, return mgr_desc[channel].name; } -static u32 dispc_mgr_get_vsync_irq(struct dispc_device *dispc, - enum omap_channel channel) +static bool dispc_mgr_has_framedone(struct dispc_device *dispc, + enum omap_channel channel) { - return mgr_desc[channel].vsync_irq; -} - -static u32 dispc_mgr_get_framedone_irq(struct dispc_device *dispc, - enum omap_channel channel) -{ - if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc->feat->no_framedone_tv) - return 0; - - return mgr_desc[channel].framedone_irq; -} - -static u32 dispc_mgr_get_sync_lost_irq(struct dispc_device *dispc, - enum omap_channel channel) -{ - return mgr_desc[channel].sync_lost_irq; -} - -u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc) -{ - return DISPC_IRQ_FRAMEDONEWB; + return channel != OMAP_DSS_CHANNEL_DIGIT || + dispc->feat->no_framedone_tv; } static void dispc_mgr_enable(struct dispc_device *dispc, @@ -3752,6 +3733,77 @@ static void dispc_write_irqenable(struct dispc_device *dispc, u32 mask) dispc_read_reg(dispc, DISPC_IRQENABLE); } +struct dispc_irq_bit { + u32 hw; + u64 api; +}; + +static const struct dispc_irq_bit dispc_irq_bits[] = { + { DISPC_IRQ_OCP_ERR, DSS_IRQ_DEVICE_OCP_ERR }, + + { DISPC_IRQ_FRAMEDONE, DSS_IRQ_MGR_FRAME_DONE(0) }, + { DISPC_IRQ_VSYNC, DSS_IRQ_MGR_VSYNC_EVEN(0) }, + { DISPC_IRQ_SYNC_LOST, DSS_IRQ_MGR_SYNC_LOST(0) }, + + { DISPC_IRQ_EVSYNC_EVEN, DSS_IRQ_MGR_VSYNC_EVEN(1) }, + { DISPC_IRQ_EVSYNC_ODD, DSS_IRQ_MGR_VSYNC_ODD(1) }, + { DISPC_IRQ_SYNC_LOST_DIGIT, DSS_IRQ_MGR_SYNC_LOST(1) }, + { DISPC_IRQ_FRAMEDONETV, DSS_IRQ_MGR_FRAME_DONE(1) }, + + { DISPC_IRQ_SYNC_LOST2, DSS_IRQ_MGR_SYNC_LOST(2) }, + { DISPC_IRQ_VSYNC2, DSS_IRQ_MGR_VSYNC_EVEN(2) }, + { DISPC_IRQ_FRAMEDONE2, DSS_IRQ_MGR_FRAME_DONE(2) }, + + { DISPC_IRQ_SYNC_LOST3, DSS_IRQ_MGR_SYNC_LOST(3) }, + { DISPC_IRQ_VSYNC3, DSS_IRQ_MGR_VSYNC_EVEN(3) }, + { DISPC_IRQ_FRAMEDONE3, DSS_IRQ_MGR_FRAME_DONE(3) }, + + { DISPC_IRQ_GFX_FIFO_UNDERFLOW, DSS_IRQ_OVL_FIFO_UNDERFLOW(0) }, + { DISPC_IRQ_VID1_FIFO_UNDERFLOW, DSS_IRQ_OVL_FIFO_UNDERFLOW(1) }, + { DISPC_IRQ_VID2_FIFO_UNDERFLOW, DSS_IRQ_OVL_FIFO_UNDERFLOW(2) }, + { DISPC_IRQ_VID3_FIFO_UNDERFLOW, DSS_IRQ_OVL_FIFO_UNDERFLOW(3) }, +}; + +static u64 dispc_hw_to_api_irq(u32 hw) +{ + u64 api = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(dispc_irq_bits); i++) + if (hw & dispc_irq_bits[i].hw) + api |= dispc_irq_bits[i].api; + + return api; +} + +static u32 dispc_api_to_hw_irq(u64 api) +{ + u32 hw = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(dispc_irq_bits); i++) + if (api & dispc_irq_bits[i].api) + hw |= dispc_irq_bits[i].hw; + + return hw; +} + +static u64 dispc_api_read_and_clear_irqstatus(struct dispc_device *dispc) +{ + u32 hw_status = dispc_read_irqstatus(dispc); + + dispc_clear_irqstatus(dispc, hw_status); + + return dispc_hw_to_api_irq(hw_status); +} + +static void dispc_api_write_irqenable(struct dispc_device *dispc, u64 enable) +{ + u32 hw_enable = dispc_api_to_hw_irq(enable); + + dispc_write_irqenable(dispc, hw_enable); +} + void dispc_enable_sidle(struct dispc_device *dispc) { /* SIDLEMODE: smart idle */ @@ -4473,6 +4525,10 @@ static int dispc_request_irq(struct dispc_device *dispc, irq_handler_t handler, if (dispc->user_handler != NULL) return -EBUSY; + dispc_runtime_get(dispc); + dispc_clear_irqstatus(dispc, 0xffffffff); + dispc_runtime_put(dispc); + dispc->user_handler = handler; dispc->user_data = dev_id; @@ -4610,8 +4666,7 @@ static void dispc_errata_i734_wa_fini(struct dispc_device *dispc) static void dispc_errata_i734_wa(struct dispc_device *dispc) { - u32 framedone_irq = dispc_mgr_get_framedone_irq(dispc, - OMAP_DSS_CHANNEL_LCD); + u32 framedone_irq = DISPC_IRQ_FRAMEDONE; struct omap_overlay_info ovli; struct dss_lcd_mgr_config lcd_conf; u32 gatestate; @@ -4669,9 +4724,8 @@ static void dispc_errata_i734_wa(struct dispc_device *dispc) } static const struct dispc_ops dispc_ops = { - .read_irqstatus = dispc_read_irqstatus, - .clear_irqstatus = dispc_clear_irqstatus, - .write_irqenable = dispc_write_irqenable, + .read_and_clear_irqstatus = dispc_api_read_and_clear_irqstatus, + .write_irqenable = dispc_api_write_irqenable, .request_irq = dispc_request_irq, .free_irq = dispc_free_irq, @@ -4685,13 +4739,12 @@ static const struct dispc_ops dispc_ops = { .ovl_name = dispc_ovl_name, .mgr_name = dispc_mgr_name, + .mgr_has_framedone = dispc_mgr_has_framedone, + .get_memory_bandwidth_limit = dispc_get_memory_bandwidth_limit, .mgr_enable = dispc_mgr_enable, .mgr_is_enabled = dispc_mgr_is_enabled, - .mgr_get_vsync_irq = dispc_mgr_get_vsync_irq, - .mgr_get_framedone_irq = dispc_mgr_get_framedone_irq, - .mgr_get_sync_lost_irq = dispc_mgr_get_sync_lost_irq, .mgr_go_busy = dispc_mgr_go_busy, .mgr_go = dispc_mgr_go, .mgr_set_lcd_config = dispc_mgr_set_lcd_config, diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.h b/drivers/gpu/drm/omapdrm/dss/dispc.h index e901dd1..e71266e 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.h +++ b/drivers/gpu/drm/omapdrm/dss/dispc.h @@ -18,6 +18,39 @@ #ifndef __OMAP2_DISPC_REG_H #define __OMAP2_DISPC_REG_H +/* DISPC IRQ bits */ +#define DISPC_IRQ_FRAMEDONE (1 << 0) +#define DISPC_IRQ_VSYNC (1 << 1) +#define DISPC_IRQ_EVSYNC_EVEN (1 << 2) +#define DISPC_IRQ_EVSYNC_ODD (1 << 3) +#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4) +#define DISPC_IRQ_PROG_LINE_NUM (1 << 5) +#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6) +#define DISPC_IRQ_GFX_END_WIN (1 << 7) +#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8) +#define DISPC_IRQ_OCP_ERR (1 << 9) +#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10) +#define DISPC_IRQ_VID1_END_WIN (1 << 11) +#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12) +#define DISPC_IRQ_VID2_END_WIN (1 << 13) +#define DISPC_IRQ_SYNC_LOST (1 << 14) +#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15) +#define DISPC_IRQ_WAKEUP (1 << 16) +#define DISPC_IRQ_SYNC_LOST2 (1 << 17) +#define DISPC_IRQ_VSYNC2 (1 << 18) +#define DISPC_IRQ_VID3_END_WIN (1 << 19) +#define DISPC_IRQ_VID3_FIFO_UNDERFLOW (1 << 20) +#define DISPC_IRQ_ACBIAS_COUNT_STAT2 (1 << 21) +#define DISPC_IRQ_FRAMEDONE2 (1 << 22) +#define DISPC_IRQ_FRAMEDONEWB (1 << 23) +#define DISPC_IRQ_FRAMEDONETV (1 << 24) +#define DISPC_IRQ_WBBUFFEROVERFLOW (1 << 25) +#define DISPC_IRQ_WBUNCOMPLETEERROR (1 << 26) +#define DISPC_IRQ_SYNC_LOST3 (1 << 27) +#define DISPC_IRQ_VSYNC3 (1 << 28) +#define DISPC_IRQ_ACBIAS_COUNT_STAT3 (1 << 29) +#define DISPC_IRQ_FRAMEDONE3 (1 << 30) + /* DISPC common registers */ #define DISPC_REVISION 0x0000 #define DISPC_SYSCONFIG 0x0010 diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index b84cfd8..493237e 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -27,37 +27,41 @@ #include #include -#define DISPC_IRQ_FRAMEDONE (1 << 0) -#define DISPC_IRQ_VSYNC (1 << 1) -#define DISPC_IRQ_EVSYNC_EVEN (1 << 2) -#define DISPC_IRQ_EVSYNC_ODD (1 << 3) -#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4) -#define DISPC_IRQ_PROG_LINE_NUM (1 << 5) -#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6) -#define DISPC_IRQ_GFX_END_WIN (1 << 7) -#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8) -#define DISPC_IRQ_OCP_ERR (1 << 9) -#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10) -#define DISPC_IRQ_VID1_END_WIN (1 << 11) -#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12) -#define DISPC_IRQ_VID2_END_WIN (1 << 13) -#define DISPC_IRQ_SYNC_LOST (1 << 14) -#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15) -#define DISPC_IRQ_WAKEUP (1 << 16) -#define DISPC_IRQ_SYNC_LOST2 (1 << 17) -#define DISPC_IRQ_VSYNC2 (1 << 18) -#define DISPC_IRQ_VID3_END_WIN (1 << 19) -#define DISPC_IRQ_VID3_FIFO_UNDERFLOW (1 << 20) -#define DISPC_IRQ_ACBIAS_COUNT_STAT2 (1 << 21) -#define DISPC_IRQ_FRAMEDONE2 (1 << 22) -#define DISPC_IRQ_FRAMEDONEWB (1 << 23) -#define DISPC_IRQ_FRAMEDONETV (1 << 24) -#define DISPC_IRQ_WBBUFFEROVERFLOW (1 << 25) -#define DISPC_IRQ_WBUNCOMPLETEERROR (1 << 26) -#define DISPC_IRQ_SYNC_LOST3 (1 << 27) -#define DISPC_IRQ_VSYNC3 (1 << 28) -#define DISPC_IRQ_ACBIAS_COUNT_STAT3 (1 << 29) -#define DISPC_IRQ_FRAMEDONE3 (1 << 30) +#define DSS_MAX_CHANNELS 8 +#define DSS_MAX_OVLS 8 + +/* + * Based on the above 2 defines the bellow defines describe following + * u64 IRQ bits: + * + * bit group |dev |mrg0|mrg1|mrg2|mrg3|mrg4|mrg5|mrg6|mrg7| ovl0-7 | | + * bit use |D |FEOL|FEOL|FEOL|FEOL|FEOL|FEOL|FEOL|FEOL|UUUU|UUUU| | | | | | + * bit number|0-3 |4-7 |8-11| 12-35 | 36-43 | 44-63 | + * + * device bits: D = OCP error + * mgr bits: F = frame done, E = vsync even, O = vsync odd, L = sync lost + * ovl bits: U = fifo underflow + */ +#define DSS_IRQ_DEVICE_OCP_ERR BIT_ULL(0) + +#define DSS_IRQ_MGR_BIT_N(ch, bit) (4 + 4 * ch + bit) +#define DSS_IRQ_OVL_BIT_N(ovl, bit) \ + (DSS_IRQ_MGR_BIT_N(DSS_MAX_CHANNELS, 0) + 1 * ovl + bit) + +#define DSS_IRQ_MGR_BIT(ch, bit) BIT_ULL(DSS_IRQ_MGR_BIT_N(ch, bit)) +#define DSS_IRQ_OVL_BIT(ovl, bit) BIT_ULL(DSS_IRQ_OVL_BIT_N(ovl, bit)) + +#define DSS_IRQ_MGR_MASK(ch) \ + GENMASK_ULL(DSS_IRQ_MGR_BIT_N(ch, 3), DSS_IRQ_MGR_BIT_N(ch, 0)) +#define DSS_IRQ_OVL_MASK(ovl) \ + GENMASK_ULL(DSS_IRQ_OVL_BIT_N(ovl, 0), DSS_IRQ_OVL_BIT_N(ovl, 0)) + +#define DSS_IRQ_MGR_FRAME_DONE(ch) DSS_IRQ_MGR_BIT(ch, 0) +#define DSS_IRQ_MGR_VSYNC_EVEN(ch) DSS_IRQ_MGR_BIT(ch, 1) +#define DSS_IRQ_MGR_VSYNC_ODD(ch) DSS_IRQ_MGR_BIT(ch, 2) +#define DSS_IRQ_MGR_SYNC_LOST(ch) DSS_IRQ_MGR_BIT(ch, 3) + +#define DSS_IRQ_OVL_FIFO_UNDERFLOW(ovl) DSS_IRQ_OVL_BIT(ovl, 0) struct dss_device; struct omap_drm_private; @@ -697,9 +701,8 @@ void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev, /* dispc ops */ struct dispc_ops { - u32 (*read_irqstatus)(struct dispc_device *dispc); - void (*clear_irqstatus)(struct dispc_device *dispc, u32 mask); - void (*write_irqenable)(struct dispc_device *dispc, u32 mask); + u64 (*read_and_clear_irqstatus)(struct dispc_device *dispc); + void (*write_irqenable)(struct dispc_device *dispc, u64 enable); int (*request_irq)(struct dispc_device *dispc, irq_handler_t handler, void *dev_id); @@ -716,18 +719,15 @@ struct dispc_ops { const char *(*mgr_name)(struct dispc_device *dispc, enum omap_channel channel); + bool (*mgr_has_framedone)(struct dispc_device *dispc, + enum omap_channel channel); + u32 (*get_memory_bandwidth_limit)(struct dispc_device *dispc); void (*mgr_enable)(struct dispc_device *dispc, enum omap_channel channel, bool enable); bool (*mgr_is_enabled)(struct dispc_device *dispc, enum omap_channel channel); - u32 (*mgr_get_vsync_irq)(struct dispc_device *dispc, - enum omap_channel channel); - u32 (*mgr_get_framedone_irq)(struct dispc_device *dispc, - enum omap_channel channel); - u32 (*mgr_get_sync_lost_irq)(struct dispc_device *dispc, - enum omap_channel channel); bool (*mgr_go_busy)(struct dispc_device *dispc, enum omap_channel channel); void (*mgr_go)(struct dispc_device *dispc, enum omap_channel channel); diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 00ec959..85fc2b8 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -153,7 +153,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) struct omap_crtc *omap_crtc = to_omap_crtc(crtc); enum omap_channel channel = omap_crtc->channel; struct omap_irq_wait *wait; - u32 framedone_irq, vsync_irq; + u64 vsync_irq; int ret; if (WARN_ON(omap_crtc->enabled == enable)) @@ -173,10 +173,8 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) omap_crtc->ignore_digit_sync_lost = true; } - framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(priv->dispc, - channel); - vsync_irq = priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, channel); - + vsync_irq = (DSS_IRQ_MGR_VSYNC_EVEN(channel) | + DSS_IRQ_MGR_VSYNC_ODD(channel)); if (enable) { wait = omap_irq_wait_init(dev, vsync_irq, 1); } else { @@ -189,8 +187,9 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) * even and odd frames. */ - if (framedone_irq) - wait = omap_irq_wait_init(dev, framedone_irq, 1); + if (priv->dispc_ops->mgr_has_framedone(priv->dispc, channel)) + wait = omap_irq_wait_init(dev, + DSS_IRQ_MGR_FRAME_DONE(channel), 1); else wait = omap_irq_wait_init(dev, vsync_irq, 2); } @@ -281,17 +280,17 @@ static const struct dss_mgr_ops mgr_ops = { * Setup, Flush and Page Flip */ -void omap_crtc_error_irq(struct drm_crtc *crtc, u32 irqstatus) +void omap_crtc_error_irq(struct drm_crtc *crtc, u64 irqstatus) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); if (omap_crtc->ignore_digit_sync_lost) { - irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT; + irqstatus &= ~DSS_IRQ_MGR_SYNC_LOST(omap_crtc->channel); if (!irqstatus) return; } - DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus); + DRM_ERROR_RATELIMITED("%s: errors: %016llx\n", omap_crtc->name, irqstatus); } void omap_crtc_vblank_irq(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.h b/drivers/gpu/drm/omapdrm/omap_crtc.h index eaab2d7..3c441ea 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.h +++ b/drivers/gpu/drm/omapdrm/omap_crtc.h @@ -37,7 +37,7 @@ void omap_crtc_pre_uninit(void); struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, struct omap_dss_device *dssdev); int omap_crtc_wait_pending(struct drm_crtc *crtc); -void omap_crtc_error_irq(struct drm_crtc *crtc, u32 irqstatus); +void omap_crtc_error_irq(struct drm_crtc *crtc, u64 irqstatus); void omap_crtc_vblank_irq(struct drm_crtc *crtc); #endif /* __OMAPDRM_CRTC_H__ */ diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 3b7ec7e..08c8c11 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -85,7 +85,8 @@ struct omap_drm_private { /* irq handling: */ spinlock_t wait_lock; /* protects the wait_list */ struct list_head wait_list; /* list of omap_irq_wait */ - u32 irq_mask; /* enabled irqs in addition to wait_list */ + u64 irq_mask; /* enabled irqs in addition to wait_list */ + u64 irq_uf_mask; /* underflow irq bits for all planes */ /* memory bandwidth limit if it is needed on the platform */ unsigned int max_bandwidth; diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c index 5cc88b6..9231962 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.c +++ b/drivers/gpu/drm/omapdrm/omap_irq.c @@ -20,7 +20,7 @@ struct omap_irq_wait { struct list_head node; wait_queue_head_t wq; - u32 irqmask; + u64 irqmask; int count; }; @@ -29,15 +29,15 @@ static void omap_irq_update(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct omap_irq_wait *wait; - u32 irqmask = priv->irq_mask; + u64 irqmask; assert_spin_locked(&priv->wait_lock); + irqmask = priv->irq_mask; + list_for_each_entry(wait, &priv->wait_list, node) irqmask |= wait->irqmask; - DBG("irqmask=%08x", irqmask); - priv->dispc_ops->write_irqenable(priv->dispc, irqmask); } @@ -48,14 +48,17 @@ static void omap_irq_wait_handler(struct omap_irq_wait *wait) } struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, - u32 irqmask, int count) + u64 waitmask, int count) { struct omap_drm_private *priv = dev->dev_private; struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL); unsigned long flags; + if (!wait) + return NULL; + init_waitqueue_head(&wait->wq); - wait->irqmask = irqmask; + wait->irqmask = waitmask; wait->count = count; spin_lock_irqsave(&priv->wait_lock, flags); @@ -108,8 +111,8 @@ int omap_irq_enable_vblank(struct drm_crtc *crtc) DBG("dev=%p, crtc=%u", dev, channel); spin_lock_irqsave(&priv->wait_lock, flags); - priv->irq_mask |= priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, - channel); + priv->irq_mask |= DSS_IRQ_MGR_VSYNC_EVEN(channel) | + DSS_IRQ_MGR_VSYNC_ODD(channel); omap_irq_update(dev); spin_unlock_irqrestore(&priv->wait_lock, flags); @@ -135,33 +138,25 @@ void omap_irq_disable_vblank(struct drm_crtc *crtc) DBG("dev=%p, crtc=%u", dev, channel); spin_lock_irqsave(&priv->wait_lock, flags); - priv->irq_mask &= ~priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, - channel); + priv->irq_mask &= ~(DSS_IRQ_MGR_VSYNC_EVEN(channel) | + DSS_IRQ_MGR_VSYNC_ODD(channel)); omap_irq_update(dev); spin_unlock_irqrestore(&priv->wait_lock, flags); } static void omap_irq_fifo_underflow(struct omap_drm_private *priv, - u32 irqstatus) + u64 irqstatus) { static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); - static const u32 irqbits[] = { DISPC_IRQ_GFX_FIFO_UNDERFLOW, - DISPC_IRQ_VID1_FIFO_UNDERFLOW, - DISPC_IRQ_VID2_FIFO_UNDERFLOW, - DISPC_IRQ_VID3_FIFO_UNDERFLOW }; - - const u32 mask = DISPC_IRQ_GFX_FIFO_UNDERFLOW - | DISPC_IRQ_VID1_FIFO_UNDERFLOW - | DISPC_IRQ_VID2_FIFO_UNDERFLOW - | DISPC_IRQ_VID3_FIFO_UNDERFLOW; unsigned int i; + u64 masked; spin_lock(&priv->wait_lock); - irqstatus &= priv->irq_mask & mask; + masked = irqstatus & priv->irq_uf_mask & priv->irq_mask; spin_unlock(&priv->wait_lock); - if (!irqstatus) + if (!masked) return; if (!__ratelimit(&_rs)) @@ -169,21 +164,20 @@ static void omap_irq_fifo_underflow(struct omap_drm_private *priv, DRM_ERROR("FIFO underflow on "); - for (i = 0; i < ARRAY_SIZE(irqbits); ++i) { - if (irqbits[i] & irqstatus) - pr_cont("%s ", priv->dispc_ops->ovl_name(priv->dispc, i)); + for (i = 0; i < DSS_MAX_OVLS; ++i) { + if (masked & DSS_IRQ_OVL_FIFO_UNDERFLOW(i)) + pr_cont("%u:%s ", i, + priv->dispc_ops->ovl_name(priv->dispc, i)); } - pr_cont("(0x%08x)\n", irqstatus); + pr_cont("(%016llx)\n", irqstatus); } static void omap_irq_ocp_error_handler(struct drm_device *dev, - u32 irqstatus) + u64 irqstatus) { - if (!(irqstatus & DISPC_IRQ_OCP_ERR)) - return; - - dev_err_ratelimited(dev->dev, "OCP error\n"); + if (irqstatus & DSS_IRQ_DEVICE_OCP_ERR) + dev_err_ratelimited(dev->dev, "OCP error\n"); } static irqreturn_t omap_irq_handler(int irq, void *arg) @@ -193,24 +187,23 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) struct omap_irq_wait *wait, *n; unsigned long flags; unsigned int id; - u32 irqstatus; + u64 irqstatus; - irqstatus = priv->dispc_ops->read_irqstatus(priv->dispc); - priv->dispc_ops->clear_irqstatus(priv->dispc, irqstatus); - priv->dispc_ops->read_irqstatus(priv->dispc); /* flush posted write */ + irqstatus = priv->dispc_ops->read_and_clear_irqstatus(priv->dispc); - VERB("irqs: %08x", irqstatus); + VERB("irqs: 0x%016llx\n", irqstatus); for (id = 0; id < priv->num_crtcs; id++) { struct drm_crtc *crtc = priv->crtcs[id]; enum omap_channel channel = omap_crtc_channel(crtc); - if (irqstatus & priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, channel)) { + if (irqstatus & (DSS_IRQ_MGR_VSYNC_EVEN(channel) | + DSS_IRQ_MGR_VSYNC_ODD(channel))) { drm_handle_vblank(dev, id); omap_crtc_vblank_irq(crtc); } - if (irqstatus & priv->dispc_ops->mgr_get_sync_lost_irq(priv->dispc, channel)) + if (irqstatus & DSS_IRQ_MGR_SYNC_LOST(channel)) omap_crtc_error_irq(crtc, irqstatus); } @@ -219,7 +212,7 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) spin_lock_irqsave(&priv->wait_lock, flags); list_for_each_entry_safe(wait, n, &priv->wait_list, node) { - if (wait->irqmask & irqstatus) + if (irqstatus & wait->irqmask) omap_irq_wait_handler(wait); } spin_unlock_irqrestore(&priv->wait_lock, flags); @@ -227,13 +220,6 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) return IRQ_HANDLED; } -static const u32 omap_underflow_irqs[] = { - [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW, - [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW, - [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW, - [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW, -}; - /* * We need a special version, instead of just using drm_irq_install(), * because we need to register the irq via omapdss. Once omapdss and @@ -244,29 +230,23 @@ static const u32 omap_underflow_irqs[] = { int omap_drm_irq_install(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; - unsigned int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc); - unsigned int max_planes; unsigned int i; int ret; spin_lock_init(&priv->wait_lock); INIT_LIST_HEAD(&priv->wait_list); - priv->irq_mask = DISPC_IRQ_OCP_ERR; - - max_planes = min(ARRAY_SIZE(priv->planes), - ARRAY_SIZE(omap_underflow_irqs)); - for (i = 0; i < max_planes; ++i) { - if (priv->planes[i]) - priv->irq_mask |= omap_underflow_irqs[i]; - } + priv->irq_mask = DSS_IRQ_DEVICE_OCP_ERR; - for (i = 0; i < num_mgrs; ++i) - priv->irq_mask |= priv->dispc_ops->mgr_get_sync_lost_irq(priv->dispc, i); + priv->irq_uf_mask = 0; + for (i = 0; i < priv->num_planes; ++i) + priv->irq_uf_mask |= DSS_IRQ_OVL_FIFO_UNDERFLOW( + omap_plane_get_id(priv->planes[i])); + priv->irq_mask |= priv->irq_uf_mask; - priv->dispc_ops->runtime_get(priv->dispc); - priv->dispc_ops->clear_irqstatus(priv->dispc, 0xffffffff); - priv->dispc_ops->runtime_put(priv->dispc); + for (i = 0; i < priv->num_crtcs; ++i) + priv->irq_mask |= DSS_IRQ_MGR_SYNC_LOST( + omap_crtc_channel(priv->crtcs[i])); ret = priv->dispc_ops->request_irq(priv->dispc, omap_irq_handler, dev); if (ret < 0) diff --git a/drivers/gpu/drm/omapdrm/omap_irq.h b/drivers/gpu/drm/omapdrm/omap_irq.h index 9d54414..8a7971d 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.h +++ b/drivers/gpu/drm/omapdrm/omap_irq.h @@ -32,7 +32,7 @@ void omap_drm_irq_uninstall(struct drm_device *dev); int omap_drm_irq_install(struct drm_device *dev); struct omap_irq_wait *omap_irq_wait_init(struct drm_device *dev, - u32 irqmask, int count); + u64 irqmask, int count); int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, unsigned long timeout); diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 61b0753..be803a2 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -239,6 +239,13 @@ static const struct drm_plane_funcs omap_plane_funcs = { .atomic_get_property = omap_plane_atomic_get_property, }; +enum omap_plane_id omap_plane_get_id(struct drm_plane *plane) +{ + struct omap_plane *omap_plane = to_omap_plane(plane); + + return omap_plane->id; +} + static const enum omap_plane_id plane_idx_to_id[] = { OMAP_DSS_GFX, OMAP_DSS_VIDEO1, diff --git a/drivers/gpu/drm/omapdrm/omap_plane.h b/drivers/gpu/drm/omapdrm/omap_plane.h index dc5e82a..dbab345 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.h +++ b/drivers/gpu/drm/omapdrm/omap_plane.h @@ -33,5 +33,6 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, u32 possible_crtcs); void omap_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj); +enum omap_plane_id omap_plane_get_id(struct drm_plane *plane); #endif /* __OMAPDRM_PLANE_H__ */