aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/pci/tw686x/tw686x-video.c
diff options
context:
space:
mode:
authorEzequiel Garcia <ezequiel@vanguardiasur.com.ar>2016-06-04 20:47:16 -0300
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-06-28 07:48:28 -0300
commit11a1697404ac8e58dd1483a280a2e799a71c3510 (patch)
tree42efa031e4224591bb33009db13110b91d49b486 /drivers/media/pci/tw686x/tw686x-video.c
parent[media] tw686x: Introduce an interface to support multiple DMA modes (diff)
downloadlinux-dev-11a1697404ac8e58dd1483a280a2e799a71c3510.tar.xz
linux-dev-11a1697404ac8e58dd1483a280a2e799a71c3510.zip
[media] tw686x: Add support for DMA contiguous interlaced frame mode
Now that the driver has the infrastructure to support more DMA modes, let's add the DMA contiguous interlaced frame mode. In this mode, the DMA P and B buffers are programmed with the user-provided buffers. When a P (or B) frame is ready, a new buffer is dequeued into P (or B). In addition to interlaced fields, the device can also be programmed to deliver alternate fields. Only interlaced mode is supported for now. Tested-by: Tim Harvey <tharvey@gateworks.com> Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/pci/tw686x/tw686x-video.c')
-rw-r--r--drivers/media/pci/tw686x/tw686x-video.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c
index c0d2a9bd5414..b5cb385e4cb1 100644
--- a/drivers/media/pci/tw686x/tw686x-video.c
+++ b/drivers/media/pci/tw686x/tw686x-video.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <media/v4l2-common.h>
#include <media/v4l2-event.h>
+#include <media/videobuf2-dma-contig.h>
#include <media/videobuf2-vmalloc.h>
#include "tw686x.h"
#include "tw686x-regs.h"
@@ -148,6 +149,53 @@ const struct tw686x_dma_ops memcpy_dma_ops = {
.field = V4L2_FIELD_INTERLACED,
};
+static void tw686x_contig_buf_refill(struct tw686x_video_channel *vc,
+ unsigned int pb)
+{
+ struct tw686x_v4l2_buf *buf;
+
+ while (!list_empty(&vc->vidq_queued)) {
+ u32 reg = pb ? VDMA_B_ADDR[vc->ch] : VDMA_P_ADDR[vc->ch];
+ dma_addr_t phys;
+
+ buf = list_first_entry(&vc->vidq_queued,
+ struct tw686x_v4l2_buf, list);
+ list_del(&buf->list);
+
+ phys = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
+ reg_write(vc->dev, reg, phys);
+
+ buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
+ vc->curr_bufs[pb] = buf;
+ return;
+ }
+ vc->curr_bufs[pb] = NULL;
+}
+
+static void tw686x_contig_cleanup(struct tw686x_dev *dev)
+{
+ vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+}
+
+static int tw686x_contig_setup(struct tw686x_dev *dev)
+{
+ dev->alloc_ctx = vb2_dma_contig_init_ctx(&dev->pci_dev->dev);
+ if (IS_ERR(dev->alloc_ctx)) {
+ dev_err(&dev->pci_dev->dev, "unable to init DMA context\n");
+ return PTR_ERR(dev->alloc_ctx);
+ }
+ return 0;
+}
+
+const struct tw686x_dma_ops contig_dma_ops = {
+ .setup = tw686x_contig_setup,
+ .cleanup = tw686x_contig_cleanup,
+ .buf_refill = tw686x_contig_buf_refill,
+ .mem_ops = &vb2_dma_contig_memops,
+ .hw_dma_mode = TW686X_FRAME_MODE,
+ .field = V4L2_FIELD_INTERLACED,
+};
+
static unsigned int tw686x_fields_map(v4l2_std_id std, unsigned int fps)
{
static const unsigned int map[15] = {
@@ -841,6 +889,8 @@ int tw686x_video_init(struct tw686x_dev *dev)
if (dev->dma_mode == TW686X_DMA_MODE_MEMCPY)
dev->dma_ops = &memcpy_dma_ops;
+ else if (dev->dma_mode == TW686X_DMA_MODE_CONTIG)
+ dev->dma_ops = &contig_dma_ops;
else
return -EINVAL;