diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2012-05-09 16:59:01 +0200 |
---|---|---|
committer | Philipp Zabel <p.zabel@pengutronix.de> | 2014-06-04 11:07:10 +0200 |
commit | 35de925ffaa67971e073d3ebf1e0600be0d0d3f1 (patch) | |
tree | d43d07842882332430c4711b38baa2e7a161647d /drivers/gpu | |
parent | 39b9004d1f626b88b775c7655d3f286e135dfec6 (diff) | |
download | op-kernel-dev-35de925ffaa67971e073d3ebf1e0600be0d0d3f1.zip op-kernel-dev-35de925ffaa67971e073d3ebf1e0600be0d0d3f1.tar.gz |
gpu: ipu-v3: Add SMFC code
The Sensor Multi Fifo Controller (SMFC) is used as a buffer between
the two CSIs (writing simultaneously) and up to four IDMAC channels.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/ipu-v3/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-common.c | 10 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-prv.h | 6 | ||||
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-smfc.c | 97 |
4 files changed, 114 insertions, 1 deletions
diff --git a/drivers/gpu/ipu-v3/Makefile b/drivers/gpu/ipu-v3/Makefile index d21cc37..1887972b 100644 --- a/drivers/gpu/ipu-v3/Makefile +++ b/drivers/gpu/ipu-v3/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o -imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o +imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o ipu-smfc.o diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 7e1f614..2aecc47 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -874,8 +874,17 @@ static int ipu_submodules_init(struct ipu_soc *ipu, goto err_dp; } + ret = ipu_smfc_init(ipu, dev, ipu_base + + devtype->cm_ofs + IPU_CM_SMFC_REG_OFS); + if (ret) { + unit = "smfc"; + goto err_smfc; + } + return 0; +err_smfc: + ipu_dp_exit(ipu); err_dp: ipu_dmfc_exit(ipu); err_dmfc: @@ -947,6 +956,7 @@ EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq); static void ipu_submodules_exit(struct ipu_soc *ipu) { + ipu_smfc_exit(ipu); ipu_dp_exit(ipu); ipu_dmfc_exit(ipu); ipu_dc_exit(ipu); diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h index 5cb075f..acf1811 100644 --- a/drivers/gpu/ipu-v3/ipu-prv.h +++ b/drivers/gpu/ipu-v3/ipu-prv.h @@ -151,6 +151,8 @@ struct ipuv3_channel { struct ipu_dc_priv; struct ipu_dmfc_priv; struct ipu_di; +struct ipu_smfc_priv; + struct ipu_devtype; struct ipu_soc { @@ -178,6 +180,7 @@ struct ipu_soc { struct ipu_dp_priv *dp_priv; struct ipu_dmfc_priv *dmfc_priv; struct ipu_di *di_priv[2]; + struct ipu_smfc_priv *smfc_priv; }; void ipu_srm_dp_sync_update(struct ipu_soc *ipu); @@ -203,4 +206,7 @@ void ipu_dc_exit(struct ipu_soc *ipu); int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base); void ipu_cpmem_exit(struct ipu_soc *ipu); +int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base); +void ipu_smfc_exit(struct ipu_soc *ipu); + #endif /* __IPU_PRV_H__ */ diff --git a/drivers/gpu/ipu-v3/ipu-smfc.c b/drivers/gpu/ipu-v3/ipu-smfc.c new file mode 100644 index 0000000..e4f85ad --- /dev/null +++ b/drivers/gpu/ipu-v3/ipu-smfc.c @@ -0,0 +1,97 @@ +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#define DEBUG +#include <linux/export.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/errno.h> +#include <linux/spinlock.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <video/imx-ipu-v3.h> + +#include "ipu-prv.h" + +struct ipu_smfc_priv { + void __iomem *base; + spinlock_t lock; +}; + +/*SMFC Registers */ +#define SMFC_MAP 0x0000 +#define SMFC_WMC 0x0004 +#define SMFC_BS 0x0008 + +int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize) +{ + struct ipu_smfc_priv *smfc = ipu->smfc_priv; + unsigned long flags; + u32 val, shift; + + spin_lock_irqsave(&smfc->lock, flags); + + shift = channel * 4; + val = readl(smfc->base + SMFC_BS); + val &= ~(0xf << shift); + val |= burstsize << shift; + writel(val, smfc->base + SMFC_BS); + + spin_unlock_irqrestore(&smfc->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize); + +int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id) +{ + struct ipu_smfc_priv *smfc = ipu->smfc_priv; + unsigned long flags; + u32 val, shift; + + spin_lock_irqsave(&smfc->lock, flags); + + shift = channel * 3; + val = readl(smfc->base + SMFC_MAP); + val &= ~(0x7 << shift); + val |= ((csi_id << 2) | mipi_id) << shift; + writel(val, smfc->base + SMFC_MAP); + + spin_unlock_irqrestore(&smfc->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_smfc_map_channel); + +int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, + unsigned long base) +{ + struct ipu_smfc_priv *smfc; + + smfc = devm_kzalloc(dev, sizeof(*smfc), GFP_KERNEL); + if (!smfc) + return -ENOMEM; + + ipu->smfc_priv = smfc; + spin_lock_init(&smfc->lock); + + smfc->base = devm_ioremap(dev, base, PAGE_SIZE); + if (!smfc->base) + return -ENOMEM; + + pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, smfc->base); + + return 0; +} + +void ipu_smfc_exit(struct ipu_soc *ipu) +{ +} |