예제 #1
0
파일: ipc.c 프로젝트: avagin/linux
/* 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
}
예제 #2
0
파일: atiixp.c 프로젝트: 19Dan01/linux
/*
 * 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);
}
예제 #3
0
파일: ssi.c 프로젝트: 020gzh/linux
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);

}
예제 #4
0
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);
	}
}
예제 #5
0
파일: stm32_i2s.c 프로젝트: lfd/PreemptRT
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;
}
예제 #6
0
/**
 * 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);
	}
}
예제 #7
0
파일: stm32_spdifrx.c 프로젝트: mdamt/linux
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;
}