Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/media/pci/cobalt/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  cobalt-irq.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  cobalt interrupt handling
 *
 *  Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
 *  All rights reserved.
 */


#include <media/i2c/adv7604.h>

#include "cobalt-driver.h"
#include "cobalt-irq.h"
#include "cobalt-omnitek.h"

static void cobalt_dma_stream_queue_handler(struct cobalt_stream *s)
{
 struct cobalt *cobalt = s->cobalt;
 int rx = s->video_channel;
 struct m00473_freewheel_regmap __iomem *fw =
  COBALT_CVI_FREEWHEEL(s->cobalt, rx);
 struct m00233_video_measure_regmap __iomem *vmr =
  COBALT_CVI_VMR(s->cobalt, rx);
 struct m00389_cvi_regmap __iomem *cvi =
  COBALT_CVI(s->cobalt, rx);
 struct m00479_clk_loss_detector_regmap __iomem *clkloss =
  COBALT_CVI_CLK_LOSS(s->cobalt, rx);
 struct cobalt_buffer *cb;
 bool skip = false;

 spin_lock(&s->irqlock);

 if (list_empty(&s->bufs)) {
  pr_err("no buffers!\n");
  spin_unlock(&s->irqlock);
  return;
 }

 /* Give the fresh filled up buffer to the user.
 * Note that the interrupt is only sent if the DMA can continue
 * with a new buffer, so it is always safe to return this buffer
 * to userspace. */

 cb = list_first_entry(&s->bufs, struct cobalt_buffer, list);
 list_del(&cb->list);
 spin_unlock(&s->irqlock);

 if (s->is_audio || s->is_output)
  goto done;

 if (s->unstable_frame) {
  uint32_t stat = ioread32(&vmr->irq_status);

  iowrite32(stat, &vmr->irq_status);
  if (!(ioread32(&vmr->status) &
        M00233_STATUS_BITMAP_INIT_DONE_MSK)) {
   cobalt_dbg(1, "!init_done\n");
   if (s->enable_freewheel)
    goto restart_fw;
   goto done;
  }

  if (ioread32(&clkloss->status) &
      M00479_STATUS_BITMAP_CLOCK_MISSING_MSK) {
   iowrite32(0, &clkloss->ctrl);
   iowrite32(M00479_CTRL_BITMAP_ENABLE_MSK, &clkloss->ctrl);
   cobalt_dbg(1, "no clock\n");
   if (s->enable_freewheel)
    goto restart_fw;
   goto done;
  }
  if ((stat & (M00233_IRQ_STATUS_BITMAP_VACTIVE_AREA_MSK |
        M00233_IRQ_STATUS_BITMAP_HACTIVE_AREA_MSK)) ||
    ioread32(&vmr->vactive_area) != s->timings.bt.height ||
    ioread32(&vmr->hactive_area) != s->timings.bt.width) {
   cobalt_dbg(1, "unstable\n");
   if (s->enable_freewheel)
    goto restart_fw;
   goto done;
  }
  if (!s->enable_cvi) {
   s->enable_cvi = true;
   iowrite32(M00389_CONTROL_BITMAP_ENABLE_MSK, &cvi->control);
   goto done;
  }
  if (!(ioread32(&cvi->status) & M00389_STATUS_BITMAP_LOCK_MSK)) {
   cobalt_dbg(1, "cvi no lock\n");
   if (s->enable_freewheel)
    goto restart_fw;
   goto done;
  }
  if (!s->enable_freewheel) {
   cobalt_dbg(1, "stable\n");
   s->enable_freewheel = true;
   iowrite32(0, &fw->ctrl);
   goto done;
  }
  cobalt_dbg(1, "enabled fw\n");
  iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK |
     M00233_CONTROL_BITMAP_ENABLE_INTERRUPT_MSK,
     &vmr->control);
  iowrite32(M00473_CTRL_BITMAP_ENABLE_MSK, &fw->ctrl);
  s->enable_freewheel = false;
  s->unstable_frame = false;
  s->skip_first_frames = 2;
  skip = true;
  goto done;
 }
 if (ioread32(&fw->status) & M00473_STATUS_BITMAP_FREEWHEEL_MODE_MSK) {
restart_fw:
  cobalt_dbg(1, "lost lock\n");
  iowrite32(M00233_CONTROL_BITMAP_ENABLE_MEASURE_MSK,
     &vmr->control);
  iowrite32(M00473_CTRL_BITMAP_ENABLE_MSK |
     M00473_CTRL_BITMAP_FORCE_FREEWHEEL_MODE_MSK,
     &fw->ctrl);
  iowrite32(0, &cvi->control);
  s->unstable_frame = true;
  s->enable_freewheel = false;
  s->enable_cvi = false;
 }
done:
 if (s->skip_first_frames) {
  skip = true;
  s->skip_first_frames--;
 }
 cb->vb.vb2_buf.timestamp = ktime_get_ns();
 /* TODO: the sequence number should be read from the FPGA so we
   also know about dropped frames. */

 cb->vb.sequence = s->sequence++;
 vb2_buffer_done(&cb->vb.vb2_buf,
   (skip || s->unstable_frame) ?
   VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
}

irqreturn_t cobalt_irq_handler(int irq, void *dev_id)
{
 struct cobalt *cobalt = (struct cobalt *)dev_id;
 u32 dma_interrupt =
  cobalt_read_bar0(cobalt, DMA_INTERRUPT_STATUS_REG) & 0xffff;
 u32 mask = cobalt_read_bar1(cobalt, COBALT_SYS_STAT_MASK);
 u32 edge = cobalt_read_bar1(cobalt, COBALT_SYS_STAT_EDGE);
 int i;

 /* Clear DMA interrupt */
 cobalt_write_bar0(cobalt, DMA_INTERRUPT_STATUS_REG, dma_interrupt);
 cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK, mask & ~edge);
 cobalt_write_bar1(cobalt, COBALT_SYS_STAT_EDGE, edge);

 for (i = 0; i < COBALT_NUM_STREAMS; i++) {
  struct cobalt_stream *s = &cobalt->streams[i];
  unsigned dma_fifo_mask = s->dma_fifo_mask;

  if (dma_interrupt & (1 << s->dma_channel)) {
   cobalt->irq_dma[i]++;
   /* Give fresh buffer to user and chain newly
 * queued buffers */

   cobalt_dma_stream_queue_handler(s);
   if (!s->is_audio) {
    edge &= ~dma_fifo_mask;
    cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK,
        mask & ~edge);
   }
  }
  if (s->is_audio)
   continue;
  if (edge & s->adv_irq_mask)
   set_bit(COBALT_STREAM_FL_ADV_IRQ, &s->flags);
  if ((edge & mask & dma_fifo_mask) && vb2_is_streaming(&s->q)) {
   cobalt_info("full rx FIFO %d\n", i);
   cobalt->irq_full_fifo++;
  }
 }

 queue_work(cobalt->irq_work_queues, &cobalt->irq_work_queue);

 if (edge & mask & (COBALT_SYSSTAT_VI0_INT1_MSK |
      COBALT_SYSSTAT_VI1_INT1_MSK |
      COBALT_SYSSTAT_VI2_INT1_MSK |
      COBALT_SYSSTAT_VI3_INT1_MSK |
      COBALT_SYSSTAT_VIHSMA_INT1_MSK |
      COBALT_SYSSTAT_VOHSMA_INT1_MSK))
  cobalt->irq_adv1++;
 if (edge & mask & (COBALT_SYSSTAT_VI0_INT2_MSK |
      COBALT_SYSSTAT_VI1_INT2_MSK |
      COBALT_SYSSTAT_VI2_INT2_MSK |
      COBALT_SYSSTAT_VI3_INT2_MSK |
      COBALT_SYSSTAT_VIHSMA_INT2_MSK))
  cobalt->irq_adv2++;
 if (edge & mask & COBALT_SYSSTAT_VOHSMA_INT1_MSK)
  cobalt->irq_advout++;
 if (dma_interrupt)
  cobalt->irq_dma_tot++;
 if (!(edge & mask) && !dma_interrupt)
  cobalt->irq_none++;
 dma_interrupt = cobalt_read_bar0(cobalt, DMA_INTERRUPT_STATUS_REG);

 return IRQ_HANDLED;
}

void cobalt_irq_work_handler(struct work_struct *work)
{
 struct cobalt *cobalt =
  container_of(work, struct cobalt, irq_work_queue);
 int i;

 for (i = 0; i < COBALT_NUM_NODES; i++) {
  struct cobalt_stream *s = &cobalt->streams[i];

  if (test_and_clear_bit(COBALT_STREAM_FL_ADV_IRQ, &s->flags)) {
   u32 mask;

   v4l2_subdev_call(cobalt->streams[i].sd, core,
     interrupt_service_routine, 0, NULL);
   mask = cobalt_read_bar1(cobalt, COBALT_SYS_STAT_MASK);
   cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK,
    mask | s->adv_irq_mask);
  }
 }
}

void cobalt_irq_log_status(struct cobalt *cobalt)
{
 u32 mask;
 int i;

 cobalt_info("irq: adv1=%u adv2=%u advout=%u none=%u full=%u\n",
      cobalt->irq_adv1, cobalt->irq_adv2, cobalt->irq_advout,
      cobalt->irq_none, cobalt->irq_full_fifo);
 cobalt_info("irq: dma_tot=%u (", cobalt->irq_dma_tot);
 for (i = 0; i < COBALT_NUM_STREAMS; i++)
  pr_cont("%s%u", i ? "/" : "", cobalt->irq_dma[i]);
 pr_cont(")\n");
 cobalt->irq_dma_tot = cobalt->irq_adv1 = cobalt->irq_adv2 = 0;
 cobalt->irq_advout = cobalt->irq_none = cobalt->irq_full_fifo = 0;
 memset(cobalt->irq_dma, 0, sizeof(cobalt->irq_dma));

 mask = cobalt_read_bar1(cobalt, COBALT_SYS_STAT_MASK);
 cobalt_write_bar1(cobalt, COBALT_SYS_STAT_MASK,
   mask |
   COBALT_SYSSTAT_VI0_LOST_DATA_MSK |
   COBALT_SYSSTAT_VI1_LOST_DATA_MSK |
   COBALT_SYSSTAT_VI2_LOST_DATA_MSK |
   COBALT_SYSSTAT_VI3_LOST_DATA_MSK |
   COBALT_SYSSTAT_VIHSMA_LOST_DATA_MSK |
   COBALT_SYSSTAT_VOHSMA_LOST_DATA_MSK |
   COBALT_SYSSTAT_AUD_IN_LOST_DATA_MSK |
   COBALT_SYSSTAT_AUD_OUT_LOST_DATA_MSK);
}

Messung V0.5
C=98 H=86 G=91

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.