lkml.org 
[lkml]   [2019]   [Sep]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[Patch 03/13] media: am437x-vpfe: Rework ISR routine for clarity
    Date
    Make the ISR code simpler to follow by removing goto and
    relocating/eliminating duplicate spinlock accesses.

    Signed-off-by: Benoit Parrot <bparrot@ti.com>
    ---
    drivers/media/platform/am437x/am437x-vpfe.c | 128 ++++++++++----------
    1 file changed, 66 insertions(+), 62 deletions(-)

    diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
    index 0ecb75bf5abd..7c5b734f7143 100644
    --- a/drivers/media/platform/am437x/am437x-vpfe.c
    +++ b/drivers/media/platform/am437x/am437x-vpfe.c
    @@ -1233,22 +1233,29 @@ static int vpfe_open(struct file *file)
    * This function will get next buffer from the dma queue and
    * set the buffer address in the vpfe register for capture.
    * the buffer is marked active
    - *
    - * Assumes caller is holding vpfe->dma_queue_lock already
    */
    -static inline void vpfe_schedule_next_buffer(struct vpfe_device *vpfe)
    +static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe)
    {
    + dma_addr_t addr;
    +
    + spin_lock(&vpfe->dma_queue_lock);
    + if (list_empty(&vpfe->dma_queue)) {
    + spin_unlock(&vpfe->dma_queue_lock);
    + return;
    + }
    +
    vpfe->next_frm = list_entry(vpfe->dma_queue.next,
    struct vpfe_cap_buffer, list);
    list_del(&vpfe->next_frm->list);
    + spin_unlock(&vpfe->dma_queue_lock);

    - vpfe_set_sdr_addr(&vpfe->ccdc,
    - vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb.vb2_buf, 0));
    + addr = vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb.vb2_buf, 0);
    + vpfe_set_sdr_addr(&vpfe->ccdc, addr);
    }

    static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe)
    {
    - unsigned long addr;
    + dma_addr_t addr;

    addr = vb2_dma_contig_plane_dma_addr(&vpfe->next_frm->vb.vb2_buf, 0) +
    vpfe->field_off;
    @@ -1273,6 +1280,55 @@ static inline void vpfe_process_buffer_complete(struct vpfe_device *vpfe)
    vpfe->cur_frm = vpfe->next_frm;
    }

    +static void vpfe_handle_interlaced_irq(struct vpfe_device *vpfe,
    + enum v4l2_field field)
    +{
    + int fid;
    +
    + /* interlaced or TB capture check which field
    + * we are in hardware
    + */
    + fid = vpfe_ccdc_getfid(&vpfe->ccdc);
    +
    + /* switch the software maintained field id */
    + vpfe->field ^= 1;
    + if (fid == vpfe->field) {
    + /* we are in-sync here,continue */
    + if (fid == 0) {
    + /*
    + * One frame is just being captured. If the
    + * next frame is available, release the
    + * current frame and move on
    + */
    + if (vpfe->cur_frm != vpfe->next_frm)
    + vpfe_process_buffer_complete(vpfe);
    +
    + /*
    + * based on whether the two fields are stored
    + * interleave or separately in memory,
    + * reconfigure the CCDC memory address
    + */
    + if (field == V4L2_FIELD_SEQ_TB)
    + vpfe_schedule_bottom_field(vpfe);
    + } else {
    + /*
    + * if one field is just being captured configure
    + * the next frame get the next frame from the empty
    + * queue if no frame is available hold on to the
    + * current buffer
    + */
    + if (vpfe->cur_frm == vpfe->next_frm)
    + vpfe_schedule_next_buffer(vpfe);
    + }
    + } else if (fid == 0) {
    + /*
    + * out of sync. Recover from any hardware out-of-sync.
    + * May loose one frame
    + */
    + vpfe->field = fid;
    + }
    +}
    +
    /*
    * vpfe_isr : ISR handler for vpfe capture (VINT0)
    * @irq: irq number
    @@ -1284,76 +1340,24 @@ static inline void vpfe_process_buffer_complete(struct vpfe_device *vpfe)
    static irqreturn_t vpfe_isr(int irq, void *dev)
    {
    struct vpfe_device *vpfe = (struct vpfe_device *)dev;
    - enum v4l2_field field;
    + enum v4l2_field field = vpfe->fmt.fmt.pix.field;
    int intr_status;
    - int fid;

    intr_status = vpfe_reg_read(&vpfe->ccdc, VPFE_IRQ_STS);

    if (intr_status & VPFE_VDINT0) {
    - field = vpfe->fmt.fmt.pix.field;
    -
    if (field == V4L2_FIELD_NONE) {
    - /* handle progressive frame capture */
    if (vpfe->cur_frm != vpfe->next_frm)
    vpfe_process_buffer_complete(vpfe);
    - goto next_intr;
    - }
    -
    - /* interlaced or TB capture check which field
    - we are in hardware */
    - fid = vpfe_ccdc_getfid(&vpfe->ccdc);
    -
    - /* switch the software maintained field id */
    - vpfe->field ^= 1;
    - if (fid == vpfe->field) {
    - /* we are in-sync here,continue */
    - if (fid == 0) {
    - /*
    - * One frame is just being captured. If the
    - * next frame is available, release the
    - * current frame and move on
    - */
    - if (vpfe->cur_frm != vpfe->next_frm)
    - vpfe_process_buffer_complete(vpfe);
    - /*
    - * based on whether the two fields are stored
    - * interleave or separately in memory,
    - * reconfigure the CCDC memory address
    - */
    - if (field == V4L2_FIELD_SEQ_TB)
    - vpfe_schedule_bottom_field(vpfe);
    -
    - goto next_intr;
    - }
    - /*
    - * if one field is just being captured configure
    - * the next frame get the next frame from the empty
    - * queue if no frame is available hold on to the
    - * current buffer
    - */
    - spin_lock(&vpfe->dma_queue_lock);
    - if (!list_empty(&vpfe->dma_queue) &&
    - vpfe->cur_frm == vpfe->next_frm)
    - vpfe_schedule_next_buffer(vpfe);
    - spin_unlock(&vpfe->dma_queue_lock);
    - } else if (fid == 0) {
    - /*
    - * out of sync. Recover from any hardware out-of-sync.
    - * May loose one frame
    - */
    - vpfe->field = fid;
    + } else {
    + vpfe_handle_interlaced_irq(vpfe, field);
    }
    }

    -next_intr:
    if (intr_status & VPFE_VDINT1) {
    - spin_lock(&vpfe->dma_queue_lock);
    - if (vpfe->fmt.fmt.pix.field == V4L2_FIELD_NONE &&
    - !list_empty(&vpfe->dma_queue) &&
    + if (field == V4L2_FIELD_NONE &&
    vpfe->cur_frm == vpfe->next_frm)
    vpfe_schedule_next_buffer(vpfe);
    - spin_unlock(&vpfe->dma_queue_lock);
    }

    vpfe_clear_intr(&vpfe->ccdc, intr_status);
    --
    2.17.1
    \
     
     \ /
      Last update: 2019-09-09 18:27    [W:4.143 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site