Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35de925f authored by Philipp Zabel's avatar Philipp Zabel
Browse files

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: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent 39b9004d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
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
+10 −0
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -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__ */
+97 −0
Original line number Diff line number Diff line
/*
 * 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)
{
}
+6 −0
Original line number Diff line number Diff line
@@ -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)