aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/ipu-v3
diff options
context:
space:
mode:
authorSteve Longerbeam <slongerbeam@gmail.com>2014-06-25 18:05:42 -0700
committerPhilipp Zabel <p.zabel@pengutronix.de>2014-09-02 14:55:49 +0200
commite7268c699bbe578e6dcf02e9f7f5a267837bc18f (patch)
treed01f02172f258ea722460b3bb246d2907dc5902f /drivers/gpu/ipu-v3
parentgpu: ipu-v3: Add ipu_idmac_clear_buffer() (diff)
downloadlinux-dev-e7268c699bbe578e6dcf02e9f7f5a267837bc18f.tar.xz
linux-dev-e7268c699bbe578e6dcf02e9f7f5a267837bc18f.zip
gpu: ipu-v3: Add __ipu_idmac_reset_current_buffer()
Adds __ipu_idmac_reset_current_buffer() that resets a channel's internal current buffer pointer so that transfers start from buffer 0 on the next channel enable. This operation is required for channel linking to work correctly, for instance video capture pipelines that carry out image rotations will fail after the first streaming unless this function is called for each channel before re-enabling the channels. Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers/gpu/ipu-v3')
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 773a2fc8fed4..985a7508af3a 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -234,6 +234,25 @@ EXPORT_SYMBOL_GPL(ipu_idmac_put);
#define idma_mask(ch) (1 << ((ch) & 0x1f))
+/*
+ * This is an undocumented feature, a write one to a channel bit in
+ * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
+ * internal current buffer pointer so that transfers start from buffer
+ * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
+ * only says these are read-only registers). This operation is required
+ * for channel linking to work correctly, for instance video capture
+ * pipelines that carry out image rotations will fail after the first
+ * streaming unless this function is called for each channel before
+ * re-enabling the channels.
+ */
+static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
+{
+ struct ipu_soc *ipu = channel->ipu;
+ unsigned int chno = channel->num;
+
+ ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
+}
+
void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
bool doublebuffer)
{
@@ -250,6 +269,8 @@ void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
reg &= ~idma_mask(channel->num);
ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
+ __ipu_idmac_reset_current_buffer(channel);
+
spin_unlock_irqrestore(&ipu->lock, flags);
}
EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
@@ -455,6 +476,8 @@ int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
val &= ~idma_mask(channel->num);
ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
+ __ipu_idmac_reset_current_buffer(channel);
+
/* Set channel buffers NOT to be ready */
ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */