Skip to content

Commit

Permalink
gpu: ipu-v3: Add SMFC code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Philipp Zabel committed Jun 4, 2014
1 parent 39b9004 commit 35de925
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 1 deletion.
2 changes: 1 addition & 1 deletion drivers/gpu/ipu-v3/Makefile
Original file line number Diff line number Diff line change
@@ -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
10 changes: 10 additions & 0 deletions drivers/gpu/ipu-v3/ipu-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/ipu-v3/ipu-prv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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 changes: 97 additions & 0 deletions drivers/gpu/ipu-v3/ipu-smfc.c
Original file line number Diff line number Diff line change
@@ -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)
{
}
6 changes: 6 additions & 0 deletions include/video/imx-ipu-v3.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 35de925

Please sign in to comment.