Commit fdcaa1db authored by Dave Airlie's avatar Dave Airlie

Merge tag 'ipu-3.18' of git://git.pengutronix.de/git/pza/linux into drm-next

IPUv3 preparations for capture support

* tag 'ipu-3.18' of git://git.pengutronix.de/git/pza/linux: (26 commits)
  gpu: ipu-v3: Add ipu_dump()
  gpu: ipu-cpmem: Add ipu_cpmem_dump()
  gpu: ipu-v3: Add more planar formats support
  gpu: ipu-cpmem: Add second buffer support to ipu_cpmem_set_image()
  gpu: ipu-cpmem: Add ipu_cpmem_set_rotation()
  gpu: ipu-cpmem: Add ipu_cpmem_set_axi_id()
  gpu: ipu-cpmem: Add ipu_cpmem_set_block_mode()
  gpu: ipu-v3: Add ipu_idmac_lock_enable()
  gpu: ipu-v3: Add ipu_idmac_enable_watermark()
  gpu: ipu-v3: Add ipu_stride_to_bytes()
  gpu: ipu-v3: Add __ipu_idmac_reset_current_buffer()
  gpu: ipu-v3: Add ipu_idmac_clear_buffer()
  gpu: ipu-v3: Add ipu_idmac_buffer_is_ready()
  gpu: ipu-v3: Move IDMAC channel names to imx-ipu-v3.h
  gpu: ipu-v3: Add helper function checking if pixfmt is planar
  gpu: ipu-v3: Add rotation mode conversion utilities
  gpu: ipu-v3: Add ipu_mbus_code_to_colorspace()
  gpu: ipu-v3: smfc: Add ipu_smfc_set_watermark()
  gpu: ipu-v3: smfc: Convert to per-channel
  gpu: ipu-v3: smfc: Move enable/disable to ipu-smfc.c
  ...
parents bb6d822e 3feb049f
obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o 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 ipu-smfc.o imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-smfc.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -24,23 +24,6 @@ struct ipu_soc; ...@@ -24,23 +24,6 @@ struct ipu_soc;
#include <video/imx-ipu-v3.h> #include <video/imx-ipu-v3.h>
#define IPUV3_CHANNEL_CSI0 0
#define IPUV3_CHANNEL_CSI1 1
#define IPUV3_CHANNEL_CSI2 2
#define IPUV3_CHANNEL_CSI3 3
#define IPUV3_CHANNEL_MEM_BG_SYNC 23
#define IPUV3_CHANNEL_MEM_FG_SYNC 27
#define IPUV3_CHANNEL_MEM_DC_SYNC 28
#define IPUV3_CHANNEL_MEM_FG_SYNC_ALPHA 31
#define IPUV3_CHANNEL_MEM_DC_ASYNC 41
#define IPUV3_CHANNEL_ROT_ENC_MEM 45
#define IPUV3_CHANNEL_ROT_VF_MEM 46
#define IPUV3_CHANNEL_ROT_PP_MEM 47
#define IPUV3_CHANNEL_ROT_ENC_MEM_OUT 48
#define IPUV3_CHANNEL_ROT_VF_MEM_OUT 49
#define IPUV3_CHANNEL_ROT_PP_MEM_OUT 50
#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA 51
#define IPU_MCU_T_DEFAULT 8 #define IPU_MCU_T_DEFAULT 8
#define IPU_CM_IDMAC_REG_OFS 0x00008000 #define IPU_CM_IDMAC_REG_OFS 0x00008000
#define IPU_CM_IC_REG_OFS 0x00020000 #define IPU_CM_IC_REG_OFS 0x00020000
...@@ -85,6 +68,7 @@ struct ipu_soc; ...@@ -85,6 +68,7 @@ struct ipu_soc;
#define IPU_DISP_TASK_STAT IPU_CM_REG(0x0254) #define IPU_DISP_TASK_STAT IPU_CM_REG(0x0254)
#define IPU_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0268 + 4 * ((ch) / 32)) #define IPU_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
#define IPU_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0270 + 4 * ((ch) / 32)) #define IPU_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
#define IPU_CHA_BUF2_RDY(ch) IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
#define IPU_ALT_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0278 + 4 * ((ch) / 32)) #define IPU_ALT_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
#define IPU_ALT_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0280 + 4 * ((ch) / 32)) #define IPU_ALT_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
...@@ -148,9 +132,12 @@ struct ipuv3_channel { ...@@ -148,9 +132,12 @@ struct ipuv3_channel {
struct ipu_soc *ipu; struct ipu_soc *ipu;
}; };
struct ipu_cpmem;
struct ipu_csi;
struct ipu_dc_priv; struct ipu_dc_priv;
struct ipu_dmfc_priv; struct ipu_dmfc_priv;
struct ipu_di; struct ipu_di;
struct ipu_ic_priv;
struct ipu_smfc_priv; struct ipu_smfc_priv;
struct ipu_devtype; struct ipu_devtype;
...@@ -164,7 +151,6 @@ struct ipu_soc { ...@@ -164,7 +151,6 @@ struct ipu_soc {
void __iomem *cm_reg; void __iomem *cm_reg;
void __iomem *idmac_reg; void __iomem *idmac_reg;
struct ipu_ch_param __iomem *cpmem_base;
int usecount; int usecount;
...@@ -176,13 +162,27 @@ struct ipu_soc { ...@@ -176,13 +162,27 @@ struct ipu_soc {
int irq_err; int irq_err;
struct irq_domain *domain; struct irq_domain *domain;
struct ipu_cpmem *cpmem_priv;
struct ipu_dc_priv *dc_priv; struct ipu_dc_priv *dc_priv;
struct ipu_dp_priv *dp_priv; struct ipu_dp_priv *dp_priv;
struct ipu_dmfc_priv *dmfc_priv; struct ipu_dmfc_priv *dmfc_priv;
struct ipu_di *di_priv[2]; struct ipu_di *di_priv[2];
struct ipu_csi *csi_priv[2];
struct ipu_ic_priv *ic_priv;
struct ipu_smfc_priv *smfc_priv; struct ipu_smfc_priv *smfc_priv;
}; };
static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
{
return readl(ipu->idmac_reg + offset);
}
static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
unsigned offset)
{
writel(value, ipu->idmac_reg + offset);
}
void ipu_srm_dp_sync_update(struct ipu_soc *ipu); void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
int ipu_module_enable(struct ipu_soc *ipu, u32 mask); int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
...@@ -191,6 +191,14 @@ int ipu_module_disable(struct ipu_soc *ipu, u32 mask); ...@@ -191,6 +191,14 @@ int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno); bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms); int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms);
int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
unsigned long base, u32 module, struct clk *clk_ipu);
void ipu_csi_exit(struct ipu_soc *ipu, int id);
int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
unsigned long base, unsigned long tpmem_base);
void ipu_ic_exit(struct ipu_soc *ipu);
int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id, int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
unsigned long base, u32 module, struct clk *ipu_clk); unsigned long base, u32 module, struct clk *ipu_clk);
void ipu_di_exit(struct ipu_soc *ipu, int id); void ipu_di_exit(struct ipu_soc *ipu, int id);
......
...@@ -21,9 +21,18 @@ ...@@ -21,9 +21,18 @@
#include "ipu-prv.h" #include "ipu-prv.h"
struct ipu_smfc {
struct ipu_smfc_priv *priv;
int chno;
bool inuse;
};
struct ipu_smfc_priv { struct ipu_smfc_priv {
void __iomem *base; void __iomem *base;
spinlock_t lock; spinlock_t lock;
struct ipu_soc *ipu;
struct ipu_smfc channel[4];
int use_count;
}; };
/*SMFC Registers */ /*SMFC Registers */
...@@ -31,63 +40,166 @@ struct ipu_smfc_priv { ...@@ -31,63 +40,166 @@ struct ipu_smfc_priv {
#define SMFC_WMC 0x0004 #define SMFC_WMC 0x0004
#define SMFC_BS 0x0008 #define SMFC_BS 0x0008
int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize) int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
{ {
struct ipu_smfc_priv *smfc = ipu->smfc_priv; struct ipu_smfc_priv *priv = smfc->priv;
unsigned long flags; unsigned long flags;
u32 val, shift; u32 val, shift;
spin_lock_irqsave(&smfc->lock, flags); spin_lock_irqsave(&priv->lock, flags);
shift = channel * 4; shift = smfc->chno * 4;
val = readl(smfc->base + SMFC_BS); val = readl(priv->base + SMFC_BS);
val &= ~(0xf << shift); val &= ~(0xf << shift);
val |= burstsize << shift; val |= burstsize << shift;
writel(val, smfc->base + SMFC_BS); writel(val, priv->base + SMFC_BS);
spin_unlock_irqrestore(&smfc->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize); EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id) int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
{ {
struct ipu_smfc_priv *smfc = ipu->smfc_priv; struct ipu_smfc_priv *priv = smfc->priv;
unsigned long flags; unsigned long flags;
u32 val, shift; u32 val, shift;
spin_lock_irqsave(&smfc->lock, flags); spin_lock_irqsave(&priv->lock, flags);
shift = channel * 3; shift = smfc->chno * 3;
val = readl(smfc->base + SMFC_MAP); val = readl(priv->base + SMFC_MAP);
val &= ~(0x7 << shift); val &= ~(0x7 << shift);
val |= ((csi_id << 2) | mipi_id) << shift; val |= ((csi_id << 2) | mipi_id) << shift;
writel(val, smfc->base + SMFC_MAP); writel(val, priv->base + SMFC_MAP);
spin_unlock_irqrestore(&smfc->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ipu_smfc_map_channel); EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
{
struct ipu_smfc_priv *priv = smfc->priv;
unsigned long flags;
u32 val, shift;
spin_lock_irqsave(&priv->lock, flags);
shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
val = readl(priv->base + SMFC_WMC);
val &= ~(0x3f << shift);
val |= ((clr_level << 3) | set_level) << shift;
writel(val, priv->base + SMFC_WMC);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
int ipu_smfc_enable(struct ipu_smfc *smfc)
{
struct ipu_smfc_priv *priv = smfc->priv;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
if (!priv->use_count)
ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
priv->use_count++;
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(ipu_smfc_enable);
int ipu_smfc_disable(struct ipu_smfc *smfc)
{
struct ipu_smfc_priv *priv = smfc->priv;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
priv->use_count--;
if (!priv->use_count)
ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
if (priv->use_count < 0)
priv->use_count = 0;
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(ipu_smfc_disable);
struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
{
struct ipu_smfc_priv *priv = ipu->smfc_priv;
struct ipu_smfc *smfc, *ret;
unsigned long flags;
if (chno >= 4)
return ERR_PTR(-EINVAL);
smfc = &priv->channel[chno];
ret = smfc;
spin_lock_irqsave(&priv->lock, flags);
if (smfc->inuse) {
ret = ERR_PTR(-EBUSY);
goto unlock;
}
smfc->inuse = true;
unlock:
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
EXPORT_SYMBOL_GPL(ipu_smfc_get);
void ipu_smfc_put(struct ipu_smfc *smfc)
{
struct ipu_smfc_priv *priv = smfc->priv;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
smfc->inuse = false;
spin_unlock_irqrestore(&priv->lock, flags);
}
EXPORT_SYMBOL_GPL(ipu_smfc_put);
int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
unsigned long base) unsigned long base)
{ {
struct ipu_smfc_priv *smfc; struct ipu_smfc_priv *priv;
int i;
smfc = devm_kzalloc(dev, sizeof(*smfc), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!smfc) if (!priv)
return -ENOMEM; return -ENOMEM;
ipu->smfc_priv = smfc; ipu->smfc_priv = priv;
spin_lock_init(&smfc->lock); spin_lock_init(&priv->lock);
priv->ipu = ipu;
smfc->base = devm_ioremap(dev, base, PAGE_SIZE); priv->base = devm_ioremap(dev, base, PAGE_SIZE);
if (!smfc->base) if (!priv->base)
return -ENOMEM; return -ENOMEM;
pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, smfc->base); for (i = 0; i < 4; i++) {
priv->channel[i].priv = priv;
priv->channel[i].chno = i;
}
pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
return 0; return 0;
} }
......
...@@ -62,7 +62,6 @@ static inline int calc_bandwidth(int width, int height, unsigned int vref) ...@@ -62,7 +62,6 @@ static inline int calc_bandwidth(int width, int height, unsigned int vref)
int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
int x, int y) int x, int y)
{ {
struct ipu_ch_param __iomem *cpmem;
struct drm_gem_cma_object *cma_obj; struct drm_gem_cma_object *cma_obj;
unsigned long eba; unsigned long eba;
...@@ -75,13 +74,12 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, ...@@ -75,13 +74,12 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d", dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
&cma_obj->paddr, x, y); &cma_obj->paddr, x, y);
cpmem = ipu_get_cpmem(ipu_plane->ipu_ch); ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
eba = cma_obj->paddr + fb->offsets[0] + eba = cma_obj->paddr + fb->offsets[0] +
fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x; fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
ipu_cpmem_set_buffer(cpmem, 0, eba); ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
ipu_cpmem_set_buffer(cpmem, 1, eba); ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
/* cache offsets for subsequent pageflips */ /* cache offsets for subsequent pageflips */
ipu_plane->x = x; ipu_plane->x = x;
...@@ -97,7 +95,6 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, ...@@ -97,7 +95,6 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
uint32_t src_x, uint32_t src_y, uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h) uint32_t src_w, uint32_t src_h)
{ {
struct ipu_ch_param __iomem *cpmem;
struct device *dev = ipu_plane->base.dev->dev; struct device *dev = ipu_plane->base.dev->dev;
int ret; int ret;
...@@ -175,10 +172,9 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, ...@@ -175,10 +172,9 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
return ret; return ret;
} }
cpmem = ipu_get_cpmem(ipu_plane->ipu_ch); ipu_cpmem_zero(ipu_plane->ipu_ch);
ipu_ch_param_zero(cpmem); ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h);
ipu_cpmem_set_resolution(cpmem, src_w, src_h); ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format);
ret = ipu_cpmem_set_fmt(cpmem, fb->pixel_format);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "unsupported pixel format 0x%08x\n", dev_err(dev, "unsupported pixel format 0x%08x\n",
fb->pixel_format); fb->pixel_format);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment