/* DSP notifies host of an XRUN within FW */ static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id) { struct snd_sof_pcm_stream *stream; struct sof_ipc_stream_posn posn; struct snd_sof_pcm *spcm; int direction; spcm = snd_sof_find_spcm_comp(sdev, msg_id, &direction); if (!spcm) { dev_err(sdev->dev, "error: XRUN for unknown stream, msg_id %d\n", msg_id); return; } stream = &spcm->stream[direction]; snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn)); dev_dbg(sdev->dev, "posn XRUN: host %llx comp %d size %d\n", posn.host_posn, posn.xrun_comp_id, posn.xrun_size); #if defined(CONFIG_SND_SOC_SOF_DEBUG_XRUN_STOP) /* stop PCM on XRUN - used for pipeline debug */ memcpy(&stream->posn, &posn, sizeof(posn)); snd_pcm_stop_xrun(stream->substream); #endif }
/* * XRUN detected, and stop the PCM substream */ static void snd_atiixp_xrun_dma(struct atiixp *chip, struct atiixp_dma *dma) { if (! dma->substream || ! dma->running) return; dev_dbg(chip->card->dev, "XRUN detected (DMA %d)\n", dma->ops->type); snd_pcm_stop_xrun(dma->substream); }
static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); int is_dma = rsnd_ssi_is_dma_mode(mod); u32 status; bool elapsed = false; bool stop = false; spin_lock(&priv->lock); /* ignore all cases if not working */ if (!rsnd_io_is_working(io)) goto rsnd_ssi_interrupt_out; status = rsnd_ssi_status_get(mod); /* PIO only */ if (!is_dma && (status & DIRQ)) { struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 *buf = (u32 *)(runtime->dma_area + rsnd_dai_pointer_offset(io, 0)); /* * 8/16/32 data can be assesse to TDR/RDR register * directly as 32bit data * see rsnd_ssi_init() */ if (rsnd_io_is_play(io)) rsnd_mod_write(mod, SSITDR, *buf); else *buf = rsnd_mod_read(mod, SSIRDR); elapsed = rsnd_dai_pointer_update(io, sizeof(*buf)); } /* DMA only */ if (is_dma && (status & (UIRQ | OIRQ))) stop = true; rsnd_ssi_status_clear(mod); rsnd_ssi_interrupt_out: spin_unlock(&priv->lock); if (elapsed) rsnd_dai_period_elapsed(io); if (stop) snd_pcm_stop_xrun(io->substream); }
void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) { struct snd_pcm_substream *substream = dev_id; int dcsr; dcsr = DCSR(dma_ch); DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; if (dcsr & DCSR_ENDINTR) { snd_pcm_period_elapsed(substream); } else { printk(KERN_ERR "DMA error on channel %d (DCSR=%#x)\n", dma_ch, dcsr); snd_pcm_stop_xrun(substream); } }
static irqreturn_t stm32_i2s_isr(int irq, void *devid) { struct stm32_i2s_data *i2s = (struct stm32_i2s_data *)devid; struct platform_device *pdev = i2s->pdev; u32 sr, ier; unsigned long flags; int err = 0; regmap_read(i2s->regmap, STM32_I2S_SR_REG, &sr); regmap_read(i2s->regmap, STM32_I2S_IER_REG, &ier); flags = sr & ier; if (!flags) { dev_dbg(&pdev->dev, "Spurious IRQ sr=0x%08x, ier=0x%08x\n", sr, ier); return IRQ_NONE; } regmap_write_bits(i2s->regmap, STM32_I2S_IFCR_REG, I2S_IFCR_MASK, flags); if (flags & I2S_SR_OVR) { dev_dbg(&pdev->dev, "Overrun\n"); err = 1; } if (flags & I2S_SR_UDR) { dev_dbg(&pdev->dev, "Underrun\n"); err = 1; } if (flags & I2S_SR_TIFRE) dev_dbg(&pdev->dev, "Frame error\n"); spin_lock(&i2s->irq_lock); if (err && i2s->substream) snd_pcm_stop_xrun(i2s->substream); spin_unlock(&i2s->irq_lock); return IRQ_HANDLED; }
/** * atmel_pcm_dma_irq: SSC interrupt handler for DMAENGINE enabled SSC * * We use DMAENGINE to send/receive data to/from SSC so this ISR is only to * check if any overrun occured. */ static void atmel_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct atmel_pcm_dma_params *prtd; prtd = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (ssc_sr & prtd->mask->ssc_error) { if (snd_pcm_running(substream)) pr_warn("atmel-pcm: buffer %s on %s (SSC_SR=%#x)\n", substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "underrun" : "overrun", prtd->name, ssc_sr); /* stop RX and capture: will be enabled again at restart */ ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable); snd_pcm_stop_xrun(substream); /* now drain RHR and read status to remove xrun condition */ ssc_readx(prtd->ssc->regs, SSC_RHR); ssc_readx(prtd->ssc->regs, SSC_SR); } }
static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) { struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid; struct snd_pcm_substream *substream = spdifrx->substream; struct platform_device *pdev = spdifrx->pdev; unsigned int cr, mask, sr, imr; unsigned int flags; int err = 0, err_xrun = 0; regmap_read(spdifrx->regmap, STM32_SPDIFRX_SR, &sr); regmap_read(spdifrx->regmap, STM32_SPDIFRX_IMR, &imr); mask = imr & SPDIFRX_XIMR_MASK; /* SERR, TERR, FERR IRQs are generated if IFEIE is set */ if (mask & SPDIFRX_IMR_IFEIE) mask |= (SPDIFRX_IMR_IFEIE << 1) | (SPDIFRX_IMR_IFEIE << 2); flags = sr & mask; if (!flags) { dev_err(&pdev->dev, "Unexpected IRQ. rflags=%#x, imr=%#x\n", sr, imr); return IRQ_NONE; } /* Clear IRQs */ regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, SPDIFRX_XIFCR_MASK, flags); if (flags & SPDIFRX_SR_PERR) { dev_dbg(&pdev->dev, "Parity error\n"); err_xrun = 1; } if (flags & SPDIFRX_SR_OVR) { dev_dbg(&pdev->dev, "Overrun error\n"); err_xrun = 1; } if (flags & SPDIFRX_SR_SBD) dev_dbg(&pdev->dev, "Synchronization block detected\n"); if (flags & SPDIFRX_SR_SYNCD) { dev_dbg(&pdev->dev, "Synchronization done\n"); /* Enable spdifrx */ cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_ENABLE); regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, SPDIFRX_CR_SPDIFEN_MASK, cr); } if (flags & SPDIFRX_SR_FERR) { dev_dbg(&pdev->dev, "Frame error\n"); err = 1; } if (flags & SPDIFRX_SR_SERR) { dev_dbg(&pdev->dev, "Synchronization error\n"); err = 1; } if (flags & SPDIFRX_SR_TERR) { dev_dbg(&pdev->dev, "Timeout error\n"); err = 1; } if (err) { /* SPDIFRX in STATE_STOP. Disable SPDIFRX to clear errors */ cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, SPDIFRX_CR_SPDIFEN_MASK, cr); if (substream) snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); return IRQ_HANDLED; } if (err_xrun && substream) snd_pcm_stop_xrun(substream); return IRQ_HANDLED; }