From patchwork Thu Sep 15 18:30:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Longerbeam X-Patchwork-Id: 9334549 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 663DA60839 for ; Thu, 15 Sep 2016 18:31:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5B38F29AAF for ; Thu, 15 Sep 2016 18:31:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4F9DB29B0F; Thu, 15 Sep 2016 18:31:06 +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.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID 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 7AAE629AAF for ; Thu, 15 Sep 2016 18:31:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752027AbcIOSbF (ORCPT ); Thu, 15 Sep 2016 14:31:05 -0400 Received: from mail-pa0-f67.google.com ([209.85.220.67]:34801 "EHLO mail-pa0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751704AbcIOSbE (ORCPT ); Thu, 15 Sep 2016 14:31:04 -0400 Received: by mail-pa0-f67.google.com with SMTP id vz6so2422076pab.1 for ; Thu, 15 Sep 2016 11:31:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6DkvBuq2d0my7eMtGE9TXwd2FPB1YvphFehJ/6ZtS7E=; b=p660KnIGYSbm7g1ls1ybWsFgV2Wbbj3uAVX4gCe34PYISxJ+VaPkp8dZKX6lYhZyMg Y4xgPk8qlC8sckzlDcOe/MSdX/ueG++IRb+mk5UVY51alTkqHEDyLvm7cb0cW8DhC652 7c51JNZS9RzygKORfia0ibYOWaEVPXv+mSwLZalLw14euHwJn2pIBfBaU1QxxgAqlPci jR0mMfPvLRYG9bo3igW6k8IlGcV7rHZ7sSNJHw289eVeLvrI6xNfZxIz/MkHa03HZ3Xw +G6CzsMDfN7t/NLGV4FSPzf3EqW9nirxqM1JPtiYOEj2fyQjFqD6o+1dMFnYfE8qv13w ZRMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6DkvBuq2d0my7eMtGE9TXwd2FPB1YvphFehJ/6ZtS7E=; b=Da9dZ/oHWFH+eXMy9j8Suu0vv0NWshn2Scag+6rs4tXZ+G15z1B2AdvI664FNwh6Xk aosVt0ts2S31PlvUnuRDWJQS9zLmGwdBlwiXU0YzrsaRa6BhtOTrquDm5PXkNKgJE5eJ WOtcevx0Ov4JK6kwcfywiFTyXKGXI/ppW8D4emxPu9cAmBuUu+8oDS6CVNgXhEp/OBQ/ jbLdoJtZ3HAnnAFuSMRwuWQ2fIi/c0Gb6GM8rlb5a6D5G+A7+4y/5e+/H5Xhh2XiQkWj bWIaAdwsMAs7s/UgcMwyhJpCx2wj4qcQTNWfq16SZ6e27k1iHUktyyGSam9bMP+tvvdT 044A== X-Gm-Message-State: AE9vXwPlj9jYVl+B79h5o6pY06kIvfrNIfqVmKrVEbDGTF5hcdKYsTGSHNF9iQeBG1BO7w== X-Received: by 10.66.255.42 with SMTP id an10mr16904918pad.57.1473964263627; Thu, 15 Sep 2016 11:31:03 -0700 (PDT) Received: from majic.world.mentorg.com (c-73-241-2-21.hsd1.ca.comcast.net. [73.241.2.21]) by smtp.googlemail.com with ESMTPSA id yu7sm6680554pab.45.2016.09.15.11.31.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 15 Sep 2016 11:31:03 -0700 (PDT) From: Steve Longerbeam X-Google-Original-From: Steve Longerbeam To: p.zabel@pengutronix.de, tomi.valkeinen@ti.com Cc: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org, Steve Longerbeam Subject: [PATCH v6 1/3] gpu: ipu-v3: Add FSU channel linking support Date: Thu, 15 Sep 2016 11:30:49 -0700 Message-Id: <1473964251-20662-2-git-send-email-steve_longerbeam@mentor.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1473964251-20662-1-git-send-email-steve_longerbeam@mentor.com> References: <1473964251-20662-1-git-send-email-steve_longerbeam@mentor.com> Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Adds functions to link and unlink source channels to sink channels in the FSU: int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch); int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch); The channels numbers are usually IDMAC channels, but they can also be channels that do not transfer data to or from memory. The following convenience functions can be used in place of ipu_fsu_link/unlink() when both source and sink channels are IDMAC channels: int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink); int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink); So far the following links are supported: IPUV3_CHANNEL_IC_PRP_ENC_MEM -> IPUV3_CHANNEL_MEM_ROT_ENC PUV3_CHANNEL_IC_PRP_VF_MEM -> IPUV3_CHANNEL_MEM_ROT_VF IPUV3_CHANNEL_IC_PP_MEM -> IPUV3_CHANNEL_MEM_ROT_PP IPUV3_CHANNEL_CSI_DIRECT -> IPUV3_CHANNEL_CSI_VDI_PREV More links can be added to the fsu_link_info[] array. Signed-off-by: Steve Longerbeam --- drivers/gpu/ipu-v3/ipu-common.c | 131 ++++++++++++++++++++++++++++++++++++++++ drivers/gpu/ipu-v3/ipu-prv.h | 27 +++++++++ include/video/imx-ipu-v3.h | 13 ++++ 3 files changed, 171 insertions(+) diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index d230988..fe389dd 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -730,6 +730,137 @@ void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi) } EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux); + +/* Frame Synchronization Unit Channel Linking */ + +struct fsu_link_reg_info { + int chno; + u32 reg; + u32 mask; + u32 val; +}; + +struct fsu_link_info { + struct fsu_link_reg_info src; + struct fsu_link_reg_info sink; +}; + +static const struct fsu_link_info fsu_link_info[] = { + { + .src = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2, + FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC }, + .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1, + FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC }, + }, { + .src = { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2, + FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF }, + .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1, + FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF }, + }, { + .src = { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2, + FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP }, + .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1, + FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP }, + }, { + .src = { IPUV3_CHANNEL_CSI_DIRECT, 0 }, + .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1, + FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT }, + }, +}; + +static const struct fsu_link_info *find_fsu_link_info(int src, int sink) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) { + if (src == fsu_link_info[i].src.chno && + sink == fsu_link_info[i].sink.chno) + return &fsu_link_info[i]; + } + + return NULL; +} + +/* + * Links a source channel to a sink channel in the FSU. + */ +int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch) +{ + const struct fsu_link_info *link; + u32 src_reg, sink_reg; + unsigned long flags; + + link = find_fsu_link_info(src_ch, sink_ch); + if (!link) + return -EINVAL; + + spin_lock_irqsave(&ipu->lock, flags); + + if (link->src.mask) { + src_reg = ipu_cm_read(ipu, link->src.reg); + src_reg &= ~link->src.mask; + src_reg |= link->src.val; + ipu_cm_write(ipu, src_reg, link->src.reg); + } + + if (link->sink.mask) { + sink_reg = ipu_cm_read(ipu, link->sink.reg); + sink_reg &= ~link->sink.mask; + sink_reg |= link->sink.val; + ipu_cm_write(ipu, sink_reg, link->sink.reg); + } + + spin_unlock_irqrestore(&ipu->lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(ipu_fsu_link); + +/* + * Unlinks source and sink channels in the FSU. + */ +int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch) +{ + const struct fsu_link_info *link; + u32 src_reg, sink_reg; + unsigned long flags; + + link = find_fsu_link_info(src_ch, sink_ch); + if (!link) + return -EINVAL; + + spin_lock_irqsave(&ipu->lock, flags); + + if (link->src.mask) { + src_reg = ipu_cm_read(ipu, link->src.reg); + src_reg &= ~link->src.mask; + ipu_cm_write(ipu, src_reg, link->src.reg); + } + + if (link->sink.mask) { + sink_reg = ipu_cm_read(ipu, link->sink.reg); + sink_reg &= ~link->sink.mask; + ipu_cm_write(ipu, sink_reg, link->sink.reg); + } + + spin_unlock_irqrestore(&ipu->lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(ipu_fsu_unlink); + +/* Link IDMAC channels in the FSU */ +int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink) +{ + return ipu_fsu_link(src->ipu, src->num, sink->num); +} +EXPORT_SYMBOL_GPL(ipu_idmac_link); + +/* Unlink IDMAC channels in the FSU */ +int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink) +{ + return ipu_fsu_unlink(src->ipu, src->num, sink->num); +} +EXPORT_SYMBOL_GPL(ipu_idmac_unlink); + struct ipu_devtype { const char *name; unsigned long cm_ofs; diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h index fd47f8f..81baf53 100644 --- a/drivers/gpu/ipu-v3/ipu-prv.h +++ b/drivers/gpu/ipu-v3/ipu-prv.h @@ -75,6 +75,33 @@ struct ipu_soc; #define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * (n)) #define IPU_INT_STAT(n) IPU_CM_REG(0x0200 + 4 * (n)) +/* FS_PROC_FLOW1 */ +#define FS_PRPENC_ROT_SRC_SEL_MASK (0xf << 0) +#define FS_PRPENC_ROT_SRC_SEL_ENC (0x7 << 0) +#define FS_PRPVF_ROT_SRC_SEL_MASK (0xf << 8) +#define FS_PRPVF_ROT_SRC_SEL_VF (0x8 << 8) +#define FS_PP_SRC_SEL_MASK (0xf << 12) +#define FS_PP_ROT_SRC_SEL_MASK (0xf << 16) +#define FS_PP_ROT_SRC_SEL_PP (0x5 << 16) +#define FS_VDI1_SRC_SEL_MASK (0x3 << 20) +#define FS_VDI3_SRC_SEL_MASK (0x3 << 20) +#define FS_PRP_SRC_SEL_MASK (0xf << 24) +#define FS_VDI_SRC_SEL_MASK (0x3 << 28) +#define FS_VDI_SRC_SEL_CSI_DIRECT (0x1 << 28) +#define FS_VDI_SRC_SEL_VDOA (0x2 << 28) + +/* FS_PROC_FLOW2 */ +#define FS_PRP_ENC_DEST_SEL_MASK (0xf << 0) +#define FS_PRP_ENC_DEST_SEL_IRT_ENC (0x1 << 0) +#define FS_PRPVF_DEST_SEL_MASK (0xf << 4) +#define FS_PRPVF_DEST_SEL_IRT_VF (0x1 << 4) +#define FS_PRPVF_ROT_DEST_SEL_MASK (0xf << 8) +#define FS_PP_DEST_SEL_MASK (0xf << 12) +#define FS_PP_DEST_SEL_IRT_PP (0x3 << 12) +#define FS_PP_ROT_DEST_SEL_MASK (0xf << 16) +#define FS_PRPENC_ROT_DEST_SEL_MASK (0xf << 20) +#define FS_PRP_DEST_SEL_MASK (0xf << 24) + #define IPU_DI0_COUNTER_RELEASE (1 << 24) #define IPU_DI1_COUNTER_RELEASE (1 << 25) diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index c3de740..49d5439 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h @@ -97,6 +97,14 @@ enum ipu_channel_irq { #define IPUV3_CHANNEL_CSI2 2 #define IPUV3_CHANNEL_CSI3 3 #define IPUV3_CHANNEL_VDI_MEM_IC_VF 5 +/* + * NOTE: channels 6,7 are unused in the IPU and are not IDMAC channels, + * but the direct CSI->VDI linking is handled the same way as IDMAC + * channel linking in the FSU via the IPU_FS_PROC_FLOW registers, so + * these channel names are used to support the direct CSI->VDI link. + */ +#define IPUV3_CHANNEL_CSI_DIRECT 6 +#define IPUV3_CHANNEL_CSI_VDI_PREV 7 #define IPUV3_CHANNEL_MEM_VDI_PREV 8 #define IPUV3_CHANNEL_MEM_VDI_CUR 9 #define IPUV3_CHANNEL_MEM_VDI_NEXT 10 @@ -133,6 +141,7 @@ enum ipu_channel_irq { #define IPUV3_CHANNEL_ROT_PP_MEM 50 #define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA 51 #define IPUV3_CHANNEL_MEM_BG_ASYNC_ALPHA 52 +#define IPUV3_NUM_CHANNELS 64 int ipu_map_irq(struct ipu_soc *ipu, int irq); int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, @@ -176,6 +185,10 @@ int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel); bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num); void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num); void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num); +int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch); +int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch); +int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink); +int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink); /* * IPU Channel Parameter Memory (cpmem) functions