]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
xilinx: v4l: scd: Initial version of streaming based driver
authorSatish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
Tue, 23 Oct 2018 03:30:49 +0000 (20:30 -0700)
committerMichal Simek <michal.simek@xilinx.com>
Thu, 1 Nov 2018 10:01:41 +0000 (11:01 +0100)
This patch adds support for streaming scene change detection driver.

Signed-off-by: Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
Reviewed-by: Hyun Kwon <hyun.kwon@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/media/platform/xilinx/xilinx-scenechange-channel.c
drivers/media/platform/xilinx/xilinx-scenechange-dma.c
drivers/media/platform/xilinx/xilinx-scenechange.c
drivers/media/platform/xilinx/xilinx-scenechange.h

index 8897d8390eab9da727108e558af2890a5da7c883..1bfd9fad6a09d8d45e64ed3e2cac94946ad2e2e3 100644 (file)
@@ -4,7 +4,8 @@
  *
  * Copyright (C) 2018 Xilinx, Inc.
  *
- * Author: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ * Authors: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ *          Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
  */
 
 #include <linux/clk.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-subdev.h>
+
 #include "xilinx-scenechange.h"
+#include "xilinx-vip.h"
 
 #define XSCD_MAX_WIDTH         3840
 #define XSCD_MAX_HEIGHT                2160
 #define XSCD_MIN_WIDTH         640
 #define XSCD_MIN_HEIGHT                480
 
+#define XSCD_WIDTH_OFFSET              0x10
+#define XSCD_HEIGHT_OFFSET             0x18
+#define XSCD_STRIDE_OFFSET             0x20
+#define XSCD_VID_FMT_OFFSET            0x28
+#define XSCD_SUBSAMPLE_OFFSET          0x30
+
+/* Hardware video formats for memory based IP */
+#define XSCD_COLOR_FMT_Y8              24
+#define XSCD_COLOR_FMT_Y10             25
+
+/* Hardware video formats for streaming based IP */
+#define XSCD_COLOR_FMT_RGB             0
+#define XSCD_COLOR_FMT_YUV_444         1
+#define XSCD_COLOR_FMT_YUV_422         2
+#define XSCD_COLOR_FMT_YUV_420         4
+
+#define XSCD_V_SUBSAMPLING             16
+#define XSCD_BYTE_ALIGN                        16
+
 /* -----------------------------------------------------------------------------
  * V4L2 Subdevice Pad Operations
  */
@@ -94,6 +116,70 @@ static int xscd_set_format(struct v4l2_subdev *subdev,
        return 0;
 }
 
+static int xscd_chan_get_vid_fmt(u32 media_bus_fmt, bool memory_based)
+{
+       /*
+        * FIXME: We have same media bus codes for both 8bit and 10bit pixel
+        * formats. So, there is no way to differentiate between 8bit and 10bit
+        * formats based on media bus code. This will be fixed when we have
+        * dedicated media bus code for each format.
+        */
+       if (memory_based)
+               return XSCD_COLOR_FMT_Y8;
+
+       switch (media_bus_fmt) {
+       case MEDIA_BUS_FMT_VYYUYY8_1X24:
+               return XSCD_COLOR_FMT_YUV_420;
+       case MEDIA_BUS_FMT_UYVY8_1X16:
+               return XSCD_COLOR_FMT_YUV_422;
+       case MEDIA_BUS_FMT_VUY8_1X24:
+               return XSCD_COLOR_FMT_YUV_444;
+       case MEDIA_BUS_FMT_RBG888_1X24:
+               return XSCD_COLOR_FMT_RGB;
+       default:
+               return XSCD_COLOR_FMT_YUV_420;
+       }
+}
+
+/**
+ * xscd_chan_configure_params - Program parameters to HW registers
+ * @chan: Driver specific channel struct pointer
+ * @shared_data: Shared data
+ * @chan_offset: Register offset for a channel
+ */
+void xscd_chan_configure_params(struct xscd_chan *chan,
+                               struct xscd_shared_data *shared_data,
+                               u32 chan_offset)
+{
+       u32 vid_fmt, stride;
+
+       xscd_write(chan->iomem, XSCD_WIDTH_OFFSET + chan_offset,
+                  chan->format.width);
+
+       /* Stride is required only for memory based IP, not for streaming IP */
+       if (shared_data->memory_based) {
+               stride = roundup(chan->format.width, XSCD_BYTE_ALIGN);
+               xscd_write(chan->iomem, XSCD_STRIDE_OFFSET + chan_offset,
+                          stride);
+       }
+
+       xscd_write(chan->iomem, XSCD_HEIGHT_OFFSET + chan_offset,
+                  chan->format.height);
+
+       /* Hardware video format */
+       vid_fmt = xscd_chan_get_vid_fmt(chan->format.code,
+                                       shared_data->memory_based);
+       xscd_write(chan->iomem, XSCD_VID_FMT_OFFSET + chan_offset, vid_fmt);
+
+       /*
+        * This is the vertical subsampling factor of the input image. Instead
+        * of sampling every line to calculate the histogram, IP uses this
+        * register value to sample only specific lines of the frame.
+        */
+       xscd_write(chan->iomem, XSCD_SUBSAMPLE_OFFSET + chan_offset,
+                  XSCD_V_SUBSAMPLING);
+}
+
 /* -----------------------------------------------------------------------------
  * V4L2 Subdevice Operations
  */
@@ -102,6 +188,7 @@ static int xscd_s_stream(struct v4l2_subdev *subdev, int enable)
        struct xscd_chan *chan = to_chan(subdev);
        struct xscd_shared_data *shared_data;
        unsigned long flags;
+       u32 chan_offset;
 
        /* TODO: Re-organise shared data in a better way */
        shared_data = (struct xscd_shared_data *)chan->dev->parent->driver_data;
@@ -109,19 +196,34 @@ static int xscd_s_stream(struct v4l2_subdev *subdev, int enable)
 
        spin_lock_irqsave(&chan->dmachan.lock, flags);
 
-       if (enable) {
-               if (!shared_data->active_streams) {
-                       chan->dmachan.valid_interrupt = true;
-                       shared_data->active_streams++;
-                       xscd_dma_start_transfer(&chan->dmachan);
+       if (shared_data->memory_based) {
+               chan_offset = chan->id * XILINX_XSCD_CHAN_OFFSET;
+               xscd_chan_configure_params(chan, shared_data, chan_offset);
+               if (enable) {
+                       if (!shared_data->active_streams) {
+                               chan->dmachan.valid_interrupt = true;
+                               shared_data->active_streams++;
+                               xscd_dma_start_transfer(&chan->dmachan);
+                               xscd_dma_reset(&chan->dmachan);
+                               xscd_dma_chan_enable(&chan->dmachan,
+                                                    BIT(chan->id));
+                               xscd_dma_start(&chan->dmachan);
+                       } else {
+                               shared_data->active_streams++;
+                       }
+               } else {
+                       shared_data->active_streams--;
+               }
+       } else {
+               /* Streaming based */
+               if (enable) {
+                       xscd_chan_configure_params(chan, shared_data, chan->id);
                        xscd_dma_reset(&chan->dmachan);
                        xscd_dma_chan_enable(&chan->dmachan, BIT(chan->id));
                        xscd_dma_start(&chan->dmachan);
                } else {
-                       shared_data->active_streams++;
+                       xscd_dma_halt(&chan->dmachan);
                }
-       } else {
-               shared_data->active_streams--;
        }
 
        spin_unlock_irqrestore(&chan->dmachan.lock, flags);
@@ -273,9 +375,11 @@ static int xscd_chan_probe(struct platform_device *pdev)
 {
        struct xscd_chan *chan;
        struct v4l2_subdev *subdev;
-       struct v4l2_mbus_framefmt *default_format;
+       struct xscd_shared_data *shared_data;
        int ret;
+       u32 num_pads;
 
+       shared_data = (struct xscd_shared_data *)pdev->dev.parent->driver_data;
        chan = devm_kzalloc(&pdev->dev, sizeof(*chan), GFP_KERNEL);
        if (!chan)
                return -ENOMEM;
@@ -297,20 +401,28 @@ static int xscd_chan_probe(struct platform_device *pdev)
        subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
 
        /* Initialize default format */
-       default_format = &chan->format;
-       default_format->code = MEDIA_BUS_FMT_VYYUYY8_1X24;
-       default_format->field = V4L2_FIELD_NONE;
-       default_format->colorspace = V4L2_COLORSPACE_SRGB;
-       default_format->width = XSCD_MAX_WIDTH;
-       default_format->height = XSCD_MAX_HEIGHT;
-       chan->format = *default_format;
-       chan->pad.flags = MEDIA_PAD_FL_SINK;
-       subdev->entity.ops = &xscd_media_ops;
+       chan->format.code = MEDIA_BUS_FMT_VYYUYY8_1X24;
+       chan->format.field = V4L2_FIELD_NONE;
+       chan->format.width = XSCD_MAX_WIDTH;
+       chan->format.height = XSCD_MAX_HEIGHT;
+
+       /* Initialize media pads */
+       num_pads = shared_data->memory_based ? 1 : 2;
+       chan->pad = devm_kzalloc(&pdev->dev,
+                                sizeof(struct media_pad) * num_pads,
+                                GFP_KERNEL);
+       if (!chan->pad)
+               return -ENOMEM;
+
+       chan->pad[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       if (!shared_data->memory_based)
+               chan->pad[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
 
-       ret = media_entity_pads_init(&subdev->entity, 1, &chan->pad);
+       ret = media_entity_pads_init(&subdev->entity, num_pads, chan->pad);
        if (ret < 0)
                goto error;
 
+       subdev->entity.ops = &xscd_media_ops;
        ret = v4l2_async_register_subdev(subdev);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to register subdev\n");
index 086e2682b307ea597ddd2da0b31de47bc978c27e..69edf7fcbc6528c2dae9619bc11a7e66691defd6 100644 (file)
@@ -4,7 +4,8 @@
  *
  * Copyright (C) 2018 Xilinx, Inc.
  *
- * Author: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ * Authors: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ *          Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
  */
 
 #include <linux/bitops.h>
 #define XILINX_XSCD_CTRL_OFFSET                0x00
 #define XILINX_XSCD_GIE_OFFSET         0x04
 #define XILINX_XSCD_IE_OFFSET          0x08
-#define XILINX_XSCD_WIDTH_OFFSET       0x10
-#define XILINX_XSCD_HEIGHT_OFFSET      0x18
-#define XILINX_XSCD_STRIDE_OFFSET      0x20
-#define XILINX_XSCD_FMT_OFFSET         0x28
-#define XILINX_XSCD_SUBSAMPLE_OFFSET   0x30
 #define XILINX_XSCD_ADDR_OFFSET                0x40
 #define XILINX_XSCD_CHAN_EN_OFFSET     0x780
-#define XILINX_XSCD_FMT_Y8             24
-#define XILINX_XSCD_FMT_Y10            25
 
 /* Control Registers */
 #define XILINX_XSCD_CTRL_AP_START      BIT(0)
 #define XILINX_XSCD_CTRL_AP_DONE       BIT(1)
 #define XILINX_XSCD_CTRL_AP_IDLE       BIT(2)
 #define XILINX_XSCD_CTRL_AP_READY      BIT(3)
+#define XILINX_XSCD_CTRL_AUTO_RESTART  BIT(7)
 #define XILINX_XSCD_GIE_EN             BIT(0)
 
-#define XSCD_V_SUBSAMPLING             16
-
 /**
  * struct xscd_dma_device - Scene Change DMA device
  * @regs: I/O mapped base address
@@ -56,6 +49,7 @@
  * @common: DMA device structure
  * @chan: Driver specific DMA channel
  * @numchannels: Total number of channels
+ * @memory_based: Memory based or streaming based
  */
 struct xscd_dma_device {
        void __iomem *regs;
@@ -63,6 +57,7 @@ struct xscd_dma_device {
        struct dma_device common;
        struct xscd_dma_chan **chan;
        u32 numchannels;
+       bool memory_based;
 };
 
 /**
@@ -76,33 +71,36 @@ static irqreturn_t xscd_dma_irq_handler(int irq, void *data)
 {
        struct xscd_dma_device *dev = data;
        struct xscd_dma_chan *chan;
-       u32 chan_en = 0, id;
 
-       for (id = 0; id < dev->numchannels; id++) {
-               chan = dev->chan[id];
-               spin_lock(&chan->lock);
-               chan->idle = true;
+       if (dev->memory_based) {
+               u32 chan_en = 0, id;
 
-               if (chan->en && (!list_empty(&chan->pending_list))) {
-                       chan_en |= 1 << chan->id;
-                       chan->valid_interrupt = true;
-               } else {
-                       chan->valid_interrupt = false;
-               }
+               for (id = 0; id < dev->numchannels; id++) {
+                       chan = dev->chan[id];
+                       spin_lock(&chan->lock);
+                       chan->idle = true;
 
-               xscd_dma_start_transfer(chan);
-               spin_unlock(&chan->lock);
-       }
+                       if (chan->en && (!list_empty(&chan->pending_list))) {
+                               chan_en |= 1 << chan->id;
+                               chan->valid_interrupt = true;
+                       } else {
+                               chan->valid_interrupt = false;
+                       }
 
-       if (chan_en) {
-               xscd_dma_reset(chan);
-               xscd_dma_chan_enable(chan, chan_en);
-               xscd_dma_start(chan);
-       }
+                       xscd_dma_start_transfer(chan);
+                       spin_unlock(&chan->lock);
+               }
 
-       for (id = 0; id < dev->numchannels; id++) {
-               chan = dev->chan[id];
-               tasklet_schedule(&chan->tasklet);
+               if (chan_en) {
+                       xscd_dma_reset(chan);
+                       xscd_dma_chan_enable(chan, chan_en);
+                       xscd_dma_start(chan);
+               }
+
+               for (id = 0; id < dev->numchannels; id++) {
+                       chan = dev->chan[id];
+                       tasklet_schedule(&chan->tasklet);
+               }
        }
 
        return IRQ_HANDLED;
@@ -210,20 +208,6 @@ void xscd_dma_start_transfer(struct xscd_dma_chan *chan)
        xscd_write(chan->iomem, XILINX_XSCD_ADDR_OFFSET + chanoffset,
                   desc->sw.luma_plane_addr);
 
-       /* HW expects these parameters to be same for one transaction */
-       xscd_write(chan->iomem, (XILINX_XSCD_WIDTH_OFFSET + chanoffset),
-                  desc->sw.hsize);
-       xscd_write(chan->iomem, (XILINX_XSCD_STRIDE_OFFSET + chanoffset),
-                  desc->sw.stride);
-       xscd_write(chan->iomem, (XILINX_XSCD_HEIGHT_OFFSET + chanoffset),
-                  desc->sw.vsize);
-       xscd_write(chan->iomem, (XILINX_XSCD_FMT_OFFSET + chanoffset),
-                  XILINX_XSCD_FMT_Y8);
-
-       /* Number of times subsampled */
-       xscd_write(chan->iomem, (XILINX_XSCD_SUBSAMPLE_OFFSET + chanoffset),
-                  XSCD_V_SUBSAMPLING);
-
        list_del(&desc->node);
        chan->staged_desc = desc;
 }
@@ -371,8 +355,7 @@ static void xscd_dma_issue_pending(struct dma_chan *dchan)
 {
        struct xscd_dma_chan *chan = to_xilinx_chan(dchan);
        struct xscd_dma_device *dev = chan->xdev;
-       u32 chan_en = 0;
-       u32 id;
+       u32 chan_en = 0, id;
 
        for (id = 0; id < dev->numchannels; id++) {
                chan = dev->chan[id];
@@ -410,8 +393,17 @@ static enum dma_status xscd_dma_tx_status(struct dma_chan *dchan,
  */
 void xscd_dma_halt(struct xscd_dma_chan *chan)
 {
-       xscd_clr(chan->iomem, XILINX_XSCD_CTRL_OFFSET,
-                XILINX_XSCD_CTRL_AP_START);
+       struct xscd_dma_device *xdev = chan->xdev;
+
+       if (xdev->memory_based)
+               xscd_clr(chan->iomem, XILINX_XSCD_CTRL_OFFSET,
+                        XILINX_XSCD_CTRL_AP_START);
+       else
+               /* Streaming based */
+               xscd_clr(chan->iomem, XILINX_XSCD_CTRL_OFFSET,
+                        XILINX_XSCD_CTRL_AP_START |
+                        XILINX_XSCD_CTRL_AUTO_RESTART);
+
        chan->idle = true;
 }
 
@@ -421,8 +413,17 @@ void xscd_dma_halt(struct xscd_dma_chan *chan)
  */
 void xscd_dma_start(struct xscd_dma_chan *chan)
 {
-       xscd_set(chan->iomem, XILINX_XSCD_CTRL_OFFSET,
-                XILINX_XSCD_CTRL_AP_START);
+       struct xscd_dma_device *xdev = chan->xdev;
+
+       if (xdev->memory_based)
+               xscd_set(chan->iomem, XILINX_XSCD_CTRL_OFFSET,
+                        XILINX_XSCD_CTRL_AP_START);
+       else
+               /* Streaming based */
+               xscd_set(chan->iomem, XILINX_XSCD_CTRL_OFFSET,
+                        XILINX_XSCD_CTRL_AP_START |
+                        XILINX_XSCD_CTRL_AUTO_RESTART);
+
        chan->idle = false;
 }
 
@@ -541,6 +542,7 @@ static int xscd_dma_probe(struct platform_device *pdev)
        shared_data = (struct xscd_shared_data *)pdev->dev.parent->driver_data;
        xdev->regs = shared_data->iomem;
        xdev->chan = shared_data->dma_chan_list;
+       xdev->memory_based = shared_data->memory_based;
        dma_set_mask(xdev->dev, DMA_BIT_MASK(32));
 
        /* Initialize the DMA engine */
index f6fb0da1e5bf6762bd3bb793de5eb88afda3307a..c32ea3d88a3181cb41f837b331413efb80e9d795 100644 (file)
@@ -4,7 +4,8 @@
  *
  * Copyright (C) 2018 Xilinx, Inc.
  *
- * Author: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ * Authors: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ *          Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
  */
 
 #include "xilinx-scenechange.h"
@@ -56,8 +57,8 @@ static void xscd_chan_remove(struct platform_device *dev)
 }
 
 static
-struct platform_device *xlnx_scdma_device_init(struct platform_device *pdev,
-                                              struct device_node *node)
+struct platform_device *xilinx_scdma_device_init(struct platform_device *pdev,
+                                                struct device_node *node)
 {
        struct platform_device *dma;
        int ret;
@@ -107,7 +108,8 @@ static int xscd_parse_of(struct xscd_device *xscd)
        struct device_node *node = xscd->dev->of_node;
        int ret;
 
-       xscd->memorybased = of_property_read_bool(node, "xlnx,memorybased");
+       xscd->shared_data.memory_based =
+                       of_property_read_bool(node, "xlnx,memorybased");
        xscd->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(xscd->rst_gpio)) {
                if (PTR_ERR(xscd->rst_gpio) != -EPROBE_DEFER)
@@ -140,11 +142,6 @@ static int xscd_probe(struct platform_device *pdev)
        if (!xscd)
                return -ENOMEM;
 
-       /*
-        * Memory based is enabled by default, this can be used for streaming
-        * based driver
-        */
-       xscd->memorybased = true;
        xscd->dev = &pdev->dev;
        node = pdev->dev.of_node;
 
@@ -162,7 +159,21 @@ static int xscd_probe(struct platform_device *pdev)
 
        xscd->shared_data.iomem = xscd->iomem;
        platform_set_drvdata(pdev, (void *)&xscd->shared_data);
-       for_each_child_of_node(node, subdev_node) {
+       if (xscd->shared_data.memory_based) {
+               for_each_child_of_node(node, subdev_node) {
+                       subdev = xscd_chan_alloc(pdev, subdev_node, id);
+                       if (IS_ERR(subdev)) {
+                               dev_err(&pdev->dev,
+                                       "Failed to initialize subdev@%d\n", id);
+                               ret = PTR_ERR(subdev);
+                               goto cleanup;
+                       }
+                       xscd->subdevs[id] = subdev;
+                       id++;
+               }
+       } else {
+               /* Streaming based */
+               subdev_node = of_get_next_child(node, NULL);
                subdev = xscd_chan_alloc(pdev, subdev_node, id);
                if (IS_ERR(subdev)) {
                        dev_err(&pdev->dev,
@@ -171,17 +182,11 @@ static int xscd_probe(struct platform_device *pdev)
                        goto cleanup;
                }
                xscd->subdevs[id] = subdev;
-               id++;
        }
 
-       if (xscd->memorybased) {
-               xscd->dma_device = xlnx_scdma_device_init(pdev, xscd->dma_node);
-               if (IS_ERR(xscd->dma_node)) {
-                       ret = IS_ERR(xscd->dma_node);
-                       dev_err(&pdev->dev, "Failed to initialize the DMA\n");
-                       goto cleanup;
-               }
-       }
+       xscd->dma_device = xilinx_scdma_device_init(pdev, xscd->dma_node);
+       if (IS_ERR(xscd->dma_node))
+               dev_err(&pdev->dev, "Failed to initialize the DMA\n");
 
        dev_info(xscd->dev, "scene change detect device found!\n");
        return 0;
@@ -200,10 +205,8 @@ static int xscd_remove(struct platform_device *pdev)
        struct xscd_device *xscd = platform_get_drvdata(pdev);
        u32 i;
 
-       if (xscd->memorybased) {
-               xilinx_scdma_device_exit(xscd->dma_device);
-               xscd->dma_node = NULL;
-       }
+       xilinx_scdma_device_exit(xscd->dma_device);
+       xscd->dma_node = NULL;
 
        for (i = 0; i < xscd->numstreams; i++)
                xscd_chan_remove(xscd->subdevs[i]);
index 6faeafa5a3a42e2a157f3b16bd4bad34accabd59..618b9d42ffa30dc3cd8ec7a8e5ab58e7bc9336b0 100644 (file)
@@ -4,7 +4,8 @@
  *
  * Copyright (C) 2018 Xilinx, Inc.
  *
- * Author: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ * Authors: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ *          Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
  */
 
 #ifndef _XILINX_SCENECHANGE_H_
  * @iomem: device I/O register space remapped to kernel virtual memory
  * @dma_chan_list: List of DMA channels available
  * @active_streams: Number of active streams
+ * @memory_based: Flag to identify memory based mode
  */
 struct xscd_shared_data {
        void __iomem *iomem;
        struct xscd_dma_chan *dma_chan_list[XSCD_MAX_CHANNELS];
        u8 active_streams;
+       bool memory_based;
 };
 
 /**
  * struct xscd_device - Xilinx Scene Change Detection device structure
  * @iomem: device I/O register space remapped to kernel virtual memory
- * @memorybased: Flag to identify memory based mode
  * @numstreams: Number of streams in the design
  * @irq: Device IRQ
  * @dev: (OF) device
@@ -73,7 +75,6 @@ struct xscd_shared_data {
  */
 struct xscd_device {
        void __iomem *iomem;
-       bool memorybased;
        int numstreams;
        int irq;
        struct device *dev;
@@ -132,6 +133,7 @@ struct xscd_dma_tx_descriptor {
 struct xscd_dma_chan {
        struct xscd_dma_device *xdev;
        void __iomem *iomem;
+
        /* Descriptor operation Lock */
        spinlock_t lock;
        struct list_head chan_node;
@@ -167,7 +169,7 @@ struct xscd_chan {
        void __iomem *iomem;
        struct device *dev;
        struct v4l2_subdev subdev;
-       struct media_pad pad;
+       struct media_pad *pad;
        struct v4l2_mbus_framefmt format;
        struct v4l2_event event;
        struct xscd_dma_chan dmachan;