Пример #1
0
void
dma_rxreclaim(dma_info_t *di)
{
	void *p;

	DMA_TRACE(("%s: dma_rxreclaim\n", di->name));

	while ((p = dma_getnextrxp(di, TRUE)))
		PKTFREE(di->drv, p, FALSE);
}
Пример #2
0
/* returns a pointer to the next frame received, or NULL if there are no more */
void*
dma_rx(dma_info_t *di)
{
	void *p;
	uint len;
	int skiplen = 0;

	while ((p = dma_getnextrxp(di, FALSE))) {
		/* skip giant packets which span multiple rx descriptors */
		if (skiplen > 0) {
			skiplen -= di->rxbufsize;
			if (skiplen < 0)
				skiplen = 0;
			PKTFREE(di->drv, p, FALSE);
			continue;
		}

		len = ltoh16(*(uint16*)(PKTDATA(di->drv, p)));
		DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));

		/* bad frame length check */
		if (len > (di->rxbufsize - di->rxoffset)) {
			DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len));
			if (len > 0)
				skiplen = len - (di->rxbufsize - di->rxoffset);
			PKTFREE(di->drv, p, FALSE);
			di->hnddma.rxgiants++;
			continue;
		}

		/* set actual length */
		PKTSETLEN(di->drv, p, (di->rxoffset + len));

		break;
	}

	return (p);
}
Пример #3
0
irqreturn_t bcm947xx_i2s_isr(int irq, void *devid)
{
	uint32 intstatus, intmask;
	uint32 intstatus_new = 0;
	uint32 int_errmask = I2S_INT_DESCERR | I2S_INT_DATAERR | I2S_INT_DESC_PROTO_ERR |
	        I2S_INT_SPDIF_PAR_ERR;
	struct snd_pcm *pcm = devid;
	struct snd_soc_pcm_runtime *rtd = pcm->private_data;
	bcm947xx_i2s_info_t *snd_bcm = rtd->dai->cpu_dai->private_data;
	struct snd_pcm_substream *substream;
	struct bcm947xx_runtime_data *brtd;

//	DBG("%s enter\n", __FUNCTION__);

	intstatus = R_REG(snd_bcm->osh, &snd_bcm->regs->intstatus);

	if (BCM947XX_PCM_DEBUG_ON) {
		intmask = R_REG(snd_bcm->osh, &snd_bcm->regs->intmask);
	} else {
		(void)intmask;
	}

//	DBG("%s: intstatus 0x%x intmask 0x%x\n", __FUNCTION__, intstatus, intmask);

	/* Playback. */
	substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
	if ((brtd = bcm947xx_pcm_brtd_from_running_substream(substream))) {

		if (intstatus & I2S_INT_XMT_INT) {
			/* reclaim descriptors that have been TX'd */
			spin_lock(&brtd->lock);
			dma_getnexttxp(snd_bcm->di[0], HNDDMA_RANGE_TRANSMITTED);
			spin_unlock(&brtd->lock);

			/* clear this bit by writing a "1" back, we've serviced this */
			intstatus_new |= I2S_INT_XMT_INT;

			snd_pcm_period_elapsed(substream);
		
			spin_lock(&brtd->lock);
			snd_BUG_ON(0 == brtd->dma_loaded);
			brtd->dma_loaded--;
			spin_unlock(&brtd->lock);
		}

		if (intstatus & I2S_INT_XMTFIFO_UFLOW) {
			intstatus_new |= I2S_INT_XMTFIFO_UFLOW;
			bcm947xx_dma_abort(substream);
		}
	}

	/* Capture. */
	substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
	if ((brtd = bcm947xx_pcm_brtd_from_running_substream(substream))) {

		if (intstatus & I2S_INT_RCV_INT) {

			spin_lock(&brtd->lock);
			dma_getnextrxp(snd_bcm->di[0], false);
			spin_unlock(&brtd->lock);

			/* clear this bit by writing a "1" back, we've serviced this */
			intstatus_new |= I2S_INT_RCV_INT;

			snd_pcm_period_elapsed(substream);

			spin_lock(&brtd->lock);
			snd_BUG_ON(0 == brtd->dma_loaded);
			brtd->dma_loaded--;
			spin_unlock(&brtd->lock);
		}

		if (intstatus & I2S_INT_RCVFIFO_OFLOW) {
			intstatus_new |= I2S_INT_RCVFIFO_OFLOW;
			bcm947xx_dma_abort(substream);
		}
	}
	
	/* Common.*/
	if (intstatus & int_errmask) {
		DBG("\n\n%s: Turning off all interrupts due to error\n", __FUNCTION__);
		DBG("%s: intstatus 0x%x intmask 0x%x\n", __FUNCTION__, intstatus, intmask);


		/* something bad happened, turn off all interrupts */
		W_REG(snd_bcm->osh, &snd_bcm->regs->intmask, 0);
	}

	/* Acknowledge interrupts. */
	W_REG(snd_bcm->osh, &snd_bcm->regs->intstatus, intstatus_new);

//	DBG("%s exit\n", __FUNCTION__);

	return IRQ_RETVAL(intstatus);
}