]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
v4l: xilinx-multi-scaler: Wait for all running channels to get buffer
authorSuresh Gupta <suresh.gupta@xilinx.com>
Fri, 5 Oct 2018 14:13:04 +0000 (19:43 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Mon, 8 Oct 2018 08:58:43 +0000 (10:58 +0200)
So, this patch waits until all continuous running channels have buffer.
Driver do not support processing if any in between intermediate
channel stops streaming.

Limitation: If any intermediate channel stops the streaming,
the streaming continues for only channels which fall under a
low number of stop channel. In this case if channel 0,1,2,3,4
are running and channel 3 stops, then the streaming for channels
0,1,2 will continue and driver stop processing 4th channel without
any error indications. So, application running channel 4 may wait
indefinitely if it does not implement timeout.

Signed-off-by: Suresh Gupta <suresh.gupta@xilinx.com>
Reviewed-by: Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/media/platform/xilinx/xilinx-multi-scaler.c

index 34bfc98b2843ca9033cf355749846992ef159b0e..6329acfdfea6a9b41dc675f9aa3ed956930c0a3e 100644 (file)
@@ -807,6 +807,24 @@ static int xm2msc_job_ready(void *priv)
        return 0;
 }
 
+static bool xm2msc_alljob_ready(struct xm2m_msc_dev *xm2msc)
+{
+       struct xm2msc_chan_ctx *chan_ctx;
+       unsigned int chan;
+
+       for (chan = 0; chan < xm2msc->running_chan; chan++) {
+               chan_ctx = &xm2msc->xm2msc_chan[chan];
+
+               if (!xm2msc_job_ready((void *)chan_ctx)) {
+                       dev_info(xm2msc->dev, "chan %d not ready\n",
+                                chan_ctx->num);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
 static void xm2msc_chan_abort_bufs(struct xm2msc_chan_ctx *chan_ctx)
 {
        struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
@@ -852,6 +870,9 @@ static int xm2msc_set_bufaddr(struct xm2m_msc_dev *xm2msc)
        dma_addr_t src_luma, dst_luma;
        dma_addr_t src_croma, dst_croma;
 
+       if (!xm2msc_alljob_ready(xm2msc))
+               return -EINVAL;
+
        for (chan = 0; chan < xm2msc->running_chan; chan++) {
                chan_ctx = &xm2msc->xm2msc_chan[chan];
                base = chan_ctx->regs;
@@ -860,9 +881,8 @@ static int xm2msc_set_bufaddr(struct xm2m_msc_dev *xm2msc)
                dst_vb = v4l2_m2m_next_dst_buf(chan_ctx->m2m_ctx);
 
                if (!src_vb || !dst_vb) {
-                       v4l2_err(&xm2msc->v4l2_dev, "buffer not found ");
-                       v4l2_err(&xm2msc->v4l2_dev, "src_vb = 0x%p, dst_vb = 0x%p\n",
-                                src_vb, dst_vb);
+                       v4l2_err(&xm2msc->v4l2_dev, "buffer not found chan = %d\n",
+                                chan_ctx->num);
                        return -EINVAL;
                }
 
@@ -973,7 +993,16 @@ static void xm2msc_device_run(void *priv)
 
        ret = xm2msc_set_bufaddr(xm2msc);
        if (ret) {
-               v4l2_err(&xm2msc->v4l2_dev, "Device can't be run\n");
+               /*
+                * All channel does not have buffer
+                * Currently we do not handle the removal of any Intermediate
+                * channel while streaming is going on
+                */
+               if (xm2msc->out_streamed_chan || xm2msc->cap_streamed_chan)
+                       dev_err(xm2msc->dev,
+                               "Buffer not available, streaming chan 0x%x\n",
+                               xm2msc->cap_streamed_chan);
+
                xm2msc->device_busy = false;
                return;
        }
@@ -994,7 +1023,7 @@ static void xm2msc_device_run(void *priv)
 
        xm2msc->device_busy = false;
 
-       if (xm2msc_job_ready(xm2msc->xm2msc_chan))
+       if (xm2msc_alljob_ready(xm2msc))
                xm2msc_device_run(xm2msc->xm2msc_chan);
 
        xm2msc_job_finish(xm2msc);