gpu: ipu-v3: Add SMFC code
authorPhilipp Zabel <p.zabel@pengutronix.de>
Wed, 9 May 2012 14:59:01 +0000 (16:59 +0200)
committerPhilipp Zabel <p.zabel@pengutronix.de>
Wed, 4 Jun 2014 09:07:10 +0000 (11:07 +0200)
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>
drivers/gpu/ipu-v3/Makefile
drivers/gpu/ipu-v3/ipu-common.c
drivers/gpu/ipu-v3/ipu-prv.h
drivers/gpu/ipu-v3/ipu-smfc.c [new file with mode: 0644]
include/video/imx-ipu-v3.h

index d21cc37d049896c224017fa8f692956244119cc2..1887972b4ac299b3a40c6669d2e22fb6b5d1646b 100644 (file)
@@ -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
index 7e1f614e7fbc1aa7045a0c256c874209d59c0f21..2aecc474c4783f8c98b4ba6b2838e712c1c715c7 100644 (file)
@@ -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);
index 5cb075fdd48c127a87385e0593cd7451c9d4a43b..acf181183f0be7a2c970a3352556bd815f2d0ca6 100644 (file)
@@ -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 (file)
index 0000000..e4f85ad
--- /dev/null
@@ -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)
+{
+}
index c4d14ead5837ce85b0b6fb5064cdca13e9023ab7..e639387eee3f5533d8097cf29fdca8489009f619 100644 (file)
@@ -160,6 +160,12 @@ int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
 int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
                bool bg_chan);
 
+/*
+ * IPU Sensor Multiple FIFO Controller (SMFC) functions
+ */
+int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id);
+int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize);
+
 #define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
 
 #define IPU_FIELD_UBO          IPU_CPMEM_WORD(0, 46, 22)