Move all the type of frame handling within the dcmi_irq_thread
handler and do not rely on dma_callback as previously.

This simplifies the code by having only a single path for both
compressed and uncompressed data while also making the system
more reactive since irq_handler have more chances to be called
faster than the dma completion callback.  Indeed, in case of the
dma completion callback, this run as a tasklet created by the
dma framework upon getting an interrupt from the dma and run
at a lower priority level than other irq handlers.

Signed-off-by: Alain Volmat <[email protected]>
---
 drivers/media/platform/st/stm32/stm32-dcmi.c | 97 ++++++----------------------
 1 file changed, 18 insertions(+), 79 deletions(-)

diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c 
b/drivers/media/platform/st/stm32/stm32-dcmi.c
index 1015f2d88f54..06b66095844b 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmi.c
@@ -227,8 +227,9 @@ static int dcmi_restart_capture(struct stm32_dcmi *dcmi)
 {
        struct dcmi_buf *buf;
 
+       /* Nothing to do if we are not running */
        if (dcmi->state != RUNNING)
-               return -EINVAL;
+               return 0;
 
        /* Restart a new DMA transfer with next buffer */
        if (list_empty(&dcmi->buffers)) {
@@ -242,52 +243,6 @@ static int dcmi_restart_capture(struct stm32_dcmi *dcmi)
        return dcmi_start_capture(dcmi, buf);
 }
 
-static void dcmi_dma_callback(void *param)
-{
-       struct stm32_dcmi *dcmi = (struct stm32_dcmi *)param;
-       struct dma_tx_state state;
-       enum dma_status status;
-       struct dcmi_buf *buf = dcmi->active;
-
-       spin_lock_irq(&dcmi->irqlock);
-
-       /* Check DMA status */
-       status = dmaengine_tx_status(dcmi->dma_chan, dcmi->dma_cookie, &state);
-
-       switch (status) {
-       case DMA_IN_PROGRESS:
-               dev_dbg(dcmi->dev, "%s: Received DMA_IN_PROGRESS\n", __func__);
-               break;
-       case DMA_PAUSED:
-               dev_err(dcmi->dev, "%s: Received DMA_PAUSED\n", __func__);
-               break;
-       case DMA_ERROR:
-               dev_err(dcmi->dev, "%s: Received DMA_ERROR\n", __func__);
-
-               /* Return buffer to V4L2 in error state */
-               dcmi_buffer_done(dcmi, buf, 0, -EIO);
-               break;
-       case DMA_COMPLETE:
-               dev_dbg(dcmi->dev, "%s: Received DMA_COMPLETE\n", __func__);
-
-               /* Return buffer to V4L2 */
-               dcmi_buffer_done(dcmi, buf, buf->size, 0);
-
-               spin_unlock_irq(&dcmi->irqlock);
-
-               /* Restart capture */
-               if (dcmi_restart_capture(dcmi))
-                       dev_err(dcmi->dev, "%s: Cannot restart capture on DMA 
complete\n",
-                               __func__);
-               return;
-       default:
-               dev_err(dcmi->dev, "%s: Received unknown status\n", __func__);
-               break;
-       }
-
-       spin_unlock_irq(&dcmi->irqlock);
-}
-
 static int dcmi_start_dma(struct stm32_dcmi *dcmi,
                          struct dcmi_buf *buf)
 {
@@ -344,7 +299,7 @@ static void dcmi_set_crop(struct stm32_dcmi *dcmi)
        reg_set(dcmi->regs, DCMI_CR, CR_CROP);
 }
 
-static void dcmi_process_jpeg(struct stm32_dcmi *dcmi)
+static void dcmi_process_frame(struct stm32_dcmi *dcmi)
 {
        struct dma_tx_state state;
        enum dma_status status;
@@ -354,13 +309,11 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi)
                return;
 
        /*
-        * Because of variable JPEG buffer size sent by sensor,
-        * DMA transfer never completes due to transfer size never reached.
-        * In order to ensure that all the JPEG data are transferred
-        * in active buffer memory, DMA is drained.
-        * Then DMA tx status gives the amount of data transferred
-        * to memory, which is then returned to V4L2 through the active
-        * buffer payload.
+        * At the time FRAME interrupt is received, all dma req have been sent 
to the DMA,
+        * however DMA might still be transferring data hence first synchronize 
prior to
+        * getting the status of the DMA transfer.
+        * Then DMA tx status gives the amount of data transferred to memory, 
which is then
+        * returned to V4L2 through the active buffer payload.
         */
 
        spin_unlock_irq(&dcmi->irqlock);
@@ -368,16 +321,16 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi)
        dmaengine_synchronize(dcmi->dma_chan);
        spin_lock_irq(&dcmi->irqlock);
 
-       /* Get DMA residue to get JPEG size */
+       /* Get DMA status and residue size */
        status = dmaengine_tx_status(dcmi->dma_chan, dcmi->dma_cookie, &state);
        if (status != DMA_ERROR && state.residue < buf->size) {
-               /* Return JPEG buffer to V4L2 with received JPEG buffer size */
+               /* Return buffer to V4L2 with received data size */
                dcmi_buffer_done(dcmi, buf, buf->size - state.residue, 0);
        } else {
                dcmi->errors_count++;
-               dev_err(dcmi->dev, "%s: Cannot get JPEG size from DMA\n",
-                       __func__);
-               /* Return JPEG buffer to V4L2 in ERROR state */
+               dev_err(dcmi->dev, "%s: DMA error. status: 0x%x, residue: %d\n",
+                       __func__, status, state.residue);
+               /* Return buffer to V4L2 in ERROR state */
                dcmi_buffer_done(dcmi, buf, 0, -EIO);
        }
 
@@ -385,11 +338,6 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi)
        /* Abort DMA operation */
        dmaengine_terminate_sync(dcmi->dma_chan);
        spin_lock_irq(&dcmi->irqlock);
-
-       /* Restart capture */
-       if (dcmi_restart_capture(dcmi))
-               dev_err(dcmi->dev, "%s: Cannot restart capture on JPEG 
received\n",
-                       __func__);
 }
 
 static irqreturn_t dcmi_irq_thread(int irq, void *arg)
@@ -420,12 +368,10 @@ static irqreturn_t dcmi_irq_thread(int irq, void *arg)
        if (dcmi->misr & IT_ERR)
                dcmi->errors_count++;
 
-       if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG &&
-           dcmi->misr & IT_FRAME) {
-               /* JPEG received */
-               dcmi_process_jpeg(dcmi);
-               spin_unlock_irq(&dcmi->irqlock);
-               return IRQ_HANDLED;
+       if (dcmi->misr & IT_FRAME) {
+               dcmi_process_frame(dcmi);
+               if (dcmi_restart_capture(dcmi))
+                       dev_err(dcmi->dev, "%s: Cannot restart capture\n", 
__func__);
        }
 
        spin_unlock_irq(&dcmi->irqlock);
@@ -542,10 +488,6 @@ static int dcmi_buf_prepare(struct vb2_buffer *vb)
                        return -EIO;
                }
 
-               /* Set completion callback routine for notification */
-               buf->dma_desc->callback = dcmi_dma_callback;
-               buf->dma_desc->callback_param = dcmi;
-
                /* Mark the descriptor as reusable to avoid having to prepare 
it */
                ret = dmaengine_desc_set_reuse(buf->dma_desc);
                if (ret) {
@@ -818,10 +760,7 @@ static int dcmi_start_streaming(struct vb2_queue *vq, 
unsigned int count)
        }
 
        /* Enable interruptions */
-       if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG)
-               reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
-       else
-               reg_set(dcmi->regs, DCMI_IER, IT_OVR | IT_ERR);
+       reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
 
        spin_unlock_irq(&dcmi->irqlock);
 

-- 
2.34.1

Reply via email to