Ejemplo n.º 1
0
/*
 * uni_reader_irq_handler
 * In case of error audio stream is stopped; stop action is protected via PCM
 * stream lock  to avoid race condition with trigger callback.
 */
static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
{
	irqreturn_t ret = IRQ_NONE;
	struct uniperif *reader = dev_id;
	unsigned int status;

	if (reader->state == UNIPERIF_STATE_STOPPED) {
		/* Unexpected IRQ: do nothing */
		dev_warn(reader->dev, "unexpected IRQ ");
		return IRQ_HANDLED;
	}

	/* Get interrupt status & clear them immediately */
	status = GET_UNIPERIF_ITS(reader);
	SET_UNIPERIF_ITS_BCLR(reader, status);

	/* Check for fifo overflow error */
	if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
		dev_err(reader->dev, "FIFO error detected");

		snd_pcm_stream_lock(reader->substream);
		snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock(reader->substream);

		return IRQ_HANDLED;
	}

	return ret;
}
Ejemplo n.º 2
0
/*
 * XRUN detected, and stop the PCM substream
 */
static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma)
{
    if (! dma->substream || ! dma->running)
        return;
    snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type);
    snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
}
Ejemplo n.º 3
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 atmel_pcm_dma_params *prtd;

	prtd = snd_dmaengine_pcm_get_data(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_stream_lock(substream);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock(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);
	}
}
Ejemplo n.º 4
0
/*
	Stop substream if still running.
*/
static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
{
	if (substream->runtime && snd_pcm_running(substream)) {
		snd_pcm_stream_lock_irq(substream);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
		snd_pcm_stream_unlock_irq(substream);
	}
}
Ejemplo n.º 5
0
Archivo: atiixp.c Proyecto: 3null/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_stream_lock(dma->substream);
	snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
	snd_pcm_stream_unlock(dma->substream);
}
Ejemplo n.º 6
0
static void abort_alsa_playback(struct ua101 *ua)
{
	unsigned long flags;

	if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) {
		snd_pcm_stream_lock_irqsave(ua->playback.substream, flags);
		snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock_irqrestore(ua->playback.substream, flags);
	}
}
Ejemplo n.º 7
0
static void bcm947xx_dma_abort(struct snd_pcm_substream *substream)
{
	if (snd_pcm_running(substream)) {
		unsigned long flags;
		DBG("%s XRUN\n", __FUNCTION__);
		snd_pcm_stream_lock_irqsave(substream, flags);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock_irqrestore(substream, flags);
	}
}
/*
 * XRUN detected, and stop the PCM substream
 */
static void snd_atiixp_xrun_dma(struct atiixp_modem *chip,
				struct atiixp_dma *dma)
{
	if (! dma->substream || ! dma->running)
		return;
	snd_printdd("atiixp-modem: XRUN detected (DMA %d)\n", dma->ops->type);
	snd_pcm_stream_lock(dma->substream);
	snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN);
	snd_pcm_stream_unlock(dma->substream);
}
Ejemplo n.º 9
0
static void abort_alsa_capture(struct ua101 *ua)
{
	unsigned long flags;

	if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) {
		snd_pcm_stream_lock_irqsave(ua->capture.substream, flags);
		snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock_irqrestore(ua->capture.substream, flags);
	}
}
Ejemplo n.º 10
0
static void hdmi_audio_abort_stream(struct snd_pcm_substream *substream)
{
	unsigned long flags;

	snd_pcm_stream_lock_irqsave(substream, flags);

	if (snd_pcm_running(substream))
		snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);

	snd_pcm_stream_unlock_irqrestore(substream, flags);
}
Ejemplo n.º 11
0
static void pcm_timeout_func(unsigned long data)
{
	struct tegra_runtime_data *prtd = (struct tegra_runtime_data*)data;
	struct snd_pcm_substream *substream = prtd->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;
	unsigned long current_tick = jiffies;
	
	if( jiffies_to_msecs(current_tick - prtd->pcm_timeout_tick) >= (runtime->period_size/(runtime->rate/1000))*runtime->periods*2){
		dev_err(substream->pcm->dev, "pcm_timeout_func!!! time : %d\n", jiffies_to_msecs(current_tick - prtd->pcm_timeout_tick));
		snd_pcm_stop(prtd->substream, SNDRV_PCM_STATE_XRUN);
	}
}
Ejemplo n.º 12
0
static irqreturn_t stm32_sai_isr(int irq, void *devid)
{
	struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid;
	struct snd_pcm_substream *substream = sai->substream;
	struct platform_device *pdev = sai->pdev;
	unsigned int sr, imr, flags;
	snd_pcm_state_t status = SNDRV_PCM_STATE_RUNNING;

	regmap_read(sai->regmap, STM_SAI_IMR_REGX, &imr);
	regmap_read(sai->regmap, STM_SAI_SR_REGX, &sr);

	flags = sr & imr;
	if (!flags)
		return IRQ_NONE;

	regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX, SAI_XCLRFR_MASK,
			   SAI_XCLRFR_MASK);

	if (flags & SAI_XIMR_OVRUDRIE) {
		dev_err(&pdev->dev, "IT %s\n",
			STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun");
		status = SNDRV_PCM_STATE_XRUN;
	}

	if (flags & SAI_XIMR_MUTEDETIE)
		dev_dbg(&pdev->dev, "IT mute detected\n");

	if (flags & SAI_XIMR_WCKCFGIE) {
		dev_err(&pdev->dev, "IT wrong clock configuration\n");
		status = SNDRV_PCM_STATE_DISCONNECTED;
	}

	if (flags & SAI_XIMR_CNRDYIE)
		dev_warn(&pdev->dev, "IT Codec not ready\n");

	if (flags & SAI_XIMR_AFSDETIE) {
		dev_warn(&pdev->dev, "IT Anticipated frame synchro\n");
		status = SNDRV_PCM_STATE_XRUN;
	}

	if (flags & SAI_XIMR_LFSDETIE) {
		dev_warn(&pdev->dev, "IT Late frame synchro\n");
		status = SNDRV_PCM_STATE_XRUN;
	}

	if (status != SNDRV_PCM_STATE_RUNNING) {
		snd_pcm_stream_lock(substream);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock(substream);
	}

	return IRQ_HANDLED;
}
Ejemplo n.º 13
0
static void hdmi_dai_abort(struct device *dev)
{
	struct hdmi_audio_data *ad = dev_get_drvdata(dev);

	mutex_lock(&ad->current_stream_lock);
	if (ad->current_stream && ad->current_stream->runtime &&
	    snd_pcm_running(ad->current_stream)) {
		dev_err(dev, "HDMI display disabled, aborting playback\n");
		snd_pcm_stream_lock_irq(ad->current_stream);
		snd_pcm_stop(ad->current_stream, SNDRV_PCM_STATE_DISCONNECTED);
		snd_pcm_stream_unlock_irq(ad->current_stream);
	}
	mutex_unlock(&ad->current_stream_lock);
}
Ejemplo n.º 14
0
static irqreturn_t ipq_mi2s_irq(int intrsrc, void *data)
{
	int dma_ch;
	uint32_t ret = IRQ_NONE;
	uint32_t has_xrun, pending;

	struct snd_pcm_substream *substream = data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct ipq_lpass_runtime_data_t *prtd =
		(struct ipq_lpass_runtime_data_t *)runtime->private_data;

	if (prtd)
		dma_ch = prtd->lpaif_info.dma_ch;
	else
		return IRQ_NONE;

	pending = (intrsrc
		& (UNDER_CH(dma_ch) | PER_CH(dma_ch) | ERR_CH(dma_ch)));

	has_xrun = (pending & UNDER_CH(dma_ch));

	if (unlikely(has_xrun) && substream->runtime &&
			snd_pcm_running(substream)) {
		pr_debug("%s %d: xrun warning\n", __func__, __LINE__);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
		pending &= ~UNDER_CH(dma_ch);
		ret = IRQ_HANDLED;
	}

	if (pending & PER_CH(dma_ch)) {
		if (++prtd->pcm_stream_info.period_index >= runtime->periods)
			prtd->pcm_stream_info.period_index = 0;
		snd_pcm_period_elapsed(substream);
		pending &= ~PER_CH(dma_ch);
		ret = IRQ_HANDLED;
	}

	if (pending & UNDER_CH(dma_ch)) {
		snd_pcm_period_elapsed(substream);
		pr_debug("%s %d: xrun warning\n", __func__, __LINE__);
		ret = IRQ_HANDLED;
	}

	if (pending & ERR_CH(dma_ch)) {
		pr_debug("%s %d: Bus access warning\n", __func__, __LINE__);
		ret = IRQ_HANDLED;
	}

	return ret;
}
Ejemplo n.º 15
0
static int loopback_check_format(struct loopback_cable *cable, int stream)
{
	struct snd_pcm_runtime *runtime, *cruntime;
	struct loopback_setup *setup;
	struct snd_card *card;
	int check;

	if (cable->valid != CABLE_VALID_BOTH) {
		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
			goto __notify;
		return 0;
	}
	runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
							substream->runtime;
	cruntime = cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
							substream->runtime;
	check = runtime->format != cruntime->format ||
		runtime->rate != cruntime->rate ||
		runtime->channels != cruntime->channels;
	if (!check)
		return 0;
	if (stream == SNDRV_PCM_STREAM_CAPTURE) {
		return -EIO;
	} else {
		snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
					substream, SNDRV_PCM_STATE_DRAINING);
	      __notify:
		runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
							substream->runtime;
		setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]);
		card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card;
		if (setup->format != runtime->format) {
			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
							&setup->format_id);
			setup->format = runtime->format;
		}
		if (setup->rate != runtime->rate) {
			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
							&setup->rate_id);
			setup->rate = runtime->rate;
		}
		if (setup->channels != runtime->channels) {
			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
							&setup->channels_id);
			setup->channels = runtime->channels;
		}
	}
	return 0;
}
int had_process_hot_unplug(struct snd_intelhad *intelhaddata)
{
	int caps, retval = 0;
	enum intel_had_aud_buf_type buf_id;
	struct had_pvt_data *had_stream;
	unsigned long flag_irqs;

	pr_debug("Enter:%s", __func__);

	had_stream = intelhaddata->private_data;
	buf_id = intelhaddata->curr_buf;

	spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
	if (intelhaddata->drv_status == HAD_DRV_DISCONNECTED) {
		pr_debug("Device already disconnected\n");
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		return retval;
	} else {
		/* Disable Audio */
		caps = HDMI_AUDIO_BUFFER_DONE;
		retval = had_set_caps(HAD_SET_DISABLE_AUDIO_INT, &caps);
		retval = had_set_caps(HAD_SET_DISABLE_AUDIO, NULL);
		intelhaddata->ops->enable_audio(intelhaddata->stream_info.had_substream, 0);
	}

	intelhaddata->drv_status = HAD_DRV_DISCONNECTED;
	/* Report to above ALSA layer */
	if (intelhaddata->stream_info.had_substream != NULL) {
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		pr_debug("%s: unlock -> sending pcm_stop -> lock\n", __func__);
		mutex_lock(&had_mutex);
		if (intelhaddata->stream_info.had_substream != NULL)
			snd_pcm_stop(intelhaddata->stream_info.had_substream,
				SNDRV_PCM_STATE_DISCONNECTED);
		mutex_unlock(&had_mutex);
		spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
	}

	had_stream->stream_type = HAD_INIT;
	spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
	kfree(intelhaddata->chmap->chmap);
	intelhaddata->chmap->chmap = NULL;
	pr_debug("%s: unlocked -> returned\n", __func__);

	return retval;
}
Ejemplo n.º 17
0
int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags)
{
	struct snd_pcm_runtime *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL;
	unsigned long _flags;
	int res = 0;
	unsigned char rcs0, rcs1;
	unsigned char c0, c1;

	rcs1 = reg_read(ak4114, AK4114_REG_RCS1);
	if (flags & AK4114_CHECK_NO_STAT)
		goto __rate;
	rcs0 = reg_read(ak4114, AK4114_REG_RCS0);
	spin_lock_irqsave(&ak4114->lock, _flags);
	if (rcs0 & AK4114_PAR)
		ak4114->parity_errors++;
	if (rcs1 & AK4114_V)
		ak4114->v_bit_errors++;
	if (rcs1 & AK4114_CCRC)
		ak4114->ccrc_errors++;
	if (rcs1 & AK4114_QCRC)
		ak4114->qcrc_errors++;
	c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^
                     (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK));
	c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0);
	ak4114->rcs0 = rcs0 & ~(AK4114_QINT | AK4114_CINT);
	ak4114->rcs1 = rcs1;
	spin_unlock_irqrestore(&ak4114->lock, _flags);

	ak4114_notify(ak4114, rcs0, rcs1, c0, c1);
	if (ak4114->change_callback && (c0 | c1) != 0)
		ak4114->change_callback(ak4114, c0, c1);

      __rate:
	/* compare rate */
	res = external_rate(rcs1);
	if (!(flags & AK4114_CHECK_NO_RATE) && runtime && runtime->rate != res) {
		snd_pcm_stream_lock_irqsave(ak4114->capture_substream, _flags);
		if (snd_pcm_running(ak4114->capture_substream)) {
			// printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res);
			snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING);
			res = 1;
		}
		snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags);
	}
	return res;
}
Ejemplo n.º 18
0
void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
{
	struct snd_pcm_substream *substream = dev_id;
	struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
	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 "%s: DMA error on channel %d (DCSR=%#x)\n",
			rtd->params->name, dma_ch, dcsr);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
	}
}
Ejemplo n.º 19
0
static irqreturn_t snd_stm_pcm_player_irq_handler(int irq, void *dev_id)
{
	irqreturn_t result = IRQ_NONE;
	struct snd_stm_pcm_player *pcm_player = dev_id;
	unsigned int status;

	snd_stm_printd(2, "snd_stm_pcm_player_irq_handler(irq=%d, "
			"dev_id=0x%p)\n", irq, dev_id);

	BUG_ON(!pcm_player);
	BUG_ON(!snd_stm_magic_valid(pcm_player));

	/* Get interrupt status & clear them immediately */
	preempt_disable();
	status = get__AUD_PCMOUT_ITS(pcm_player);
	set__AUD_PCMOUT_ITS_CLR(pcm_player, status);
	preempt_enable();

	/* Underflow? */
	if (unlikely(status & mask__AUD_PCMOUT_ITS__UNF__PENDING(pcm_player))) {
		snd_stm_printe("Underflow detected in PCM player '%s'!\n",
			       dev_name(pcm_player->device));

		snd_pcm_stop(pcm_player->substream, SNDRV_PCM_STATE_XRUN);

		result = IRQ_HANDLED;
	} else if (likely(status &
			mask__AUD_PCMOUT_ITS__NSAMPLE__PENDING(pcm_player))) {
		/* Period successfully played */
		do {
			BUG_ON(!pcm_player->substream);

			snd_stm_printd(2, "Period elapsed ('%s')\n",
					dev_name(pcm_player->device));
			snd_pcm_period_elapsed(pcm_player->substream);

			result = IRQ_HANDLED;
		} while (0);
	}

	/* Some alien interrupt??? */
	BUG_ON(result != IRQ_HANDLED);

	return result;
}
Ejemplo n.º 20
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_stream_lock(substream);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock(substream);
	}
}
Ejemplo n.º 21
0
static void ep93xx_pcm_buffer_finished(void *cookie, 
				       struct ep93xx_dma_buffer *buf, 
				       int bytes, int error)
{
	struct snd_pcm_substream *substream = cookie;
	struct ep93xx_runtime_data *rtd = substream->runtime->private_data;

	if (buf == rtd->buf + rtd->periods - 1)
		rtd->pointer_bytes = 0;
	else
		rtd->pointer_bytes += buf->size;

	if (!error) {
		ep93xx_dma_m2p_submit_recursive(&rtd->cl, buf);
		tasklet_schedule(&rtd->period_tasklet);
	} else {
		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
	}
}
int had_process_hot_plug(struct snd_intelhad *intelhaddata)
{
	int retval = 0;
	enum intel_had_aud_buf_type buf_id;
	struct snd_pcm_substream *substream;
	struct had_pvt_data *had_stream;
	unsigned long flag_irqs;

	pr_debug("Enter:%s", __func__);

	substream = intelhaddata->stream_info.had_substream;
	had_stream = intelhaddata->private_data;

	spin_lock_irqsave(&intelhaddata->had_spinlock, flag_irqs);
	if (intelhaddata->drv_status == HAD_DRV_CONNECTED) {
		pr_debug("Device already connected\n");
		spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);
		return retval;
	}
	buf_id = intelhaddata->curr_buf;
	intelhaddata->buff_done = buf_id;
	intelhaddata->drv_status = HAD_DRV_CONNECTED;
	spin_unlock_irqrestore(&intelhaddata->had_spinlock, flag_irqs);

	pr_debug("Processing HOT_PLUG, buf_id = %d\n", buf_id);

	/* Safety check */
	if (substream) {
		pr_debug("There should not be active PB from ALSA\n");
		pr_debug("Signifies, cable is plugged-in even before\n");
		pr_debug("processing snd_pcm_disconnect\n");
		/* Set runtime->state to hw_params done */
		snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
	}

	had_build_channel_allocation_map(intelhaddata);

	return retval;
}
Ejemplo n.º 23
0
static void pcm_afe_process_rx_pkt(uint32_t opcode,
		uint32_t token, uint32_t *payload,
		 void *priv)
{
	struct pcm_afe_info *prtd = priv;
	unsigned long dsp_flags;
	struct snd_pcm_substream *substream = NULL;
	struct snd_pcm_runtime *runtime = NULL;
	uint16_t event;

	if (prtd == NULL)
		return;
	substream =  prtd->substream;
	runtime = substream->runtime;
	pr_debug("%s\n", __func__);
	spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
	switch (opcode) {
	case AFE_EVENT_RT_PROXY_PORT_STATUS: {
		event = (uint16_t)((0xFFFF0000 & payload[0]) >> 0x10);
		switch (event) {
		case AFE_EVENT_RTPORT_START: {
			prtd->dsp_cnt = 0;
			prtd->poll_time = ((unsigned long)((
				snd_pcm_lib_period_bytes(prtd->substream)
					* 1000 * 1000)/(runtime->rate
					* runtime->channels * 2)));
			pr_debug("prtd->poll_time : %d", prtd->poll_time);
			break;
		}
		case AFE_EVENT_RTPORT_STOP:
			pr_debug("%s: event!=0\n", __func__);
			prtd->start = 0;
			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
			break;
		case AFE_EVENT_RTPORT_LOW_WM:
			pr_debug("%s: Underrun\n", __func__);
			break;
		case AFE_EVENT_RTPORT_HI_WM:
			pr_debug("%s: Overrun\n", __func__);
			break;
		default:
			break;
		}
		break;
	}
	case APR_BASIC_RSP_RESULT: {
		switch (payload[0]) {
		case AFE_SERVICE_CMD_RTPORT_RD:
			pr_debug("Read done\n");
			prtd->pcm_irq_pos += snd_pcm_lib_period_bytes
							(prtd->substream);
			snd_pcm_period_elapsed(prtd->substream);
			break;
		default:
			break;
		}
		break;
	}
	default:
		break;
	}
	spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
}
Ejemplo n.º 24
0
/**
* snd_intelhad_pcm_prepare- internal preparation before starting a stream
*
* @substream:  substream for which the function is called
*
* This function is called when a stream is started for internal preparation.
*/
static int snd_intelhad_pcm_prepare(struct snd_pcm_substream *substream)
{
	int retval;
	u32 disp_samp_freq, n_param;
	struct snd_intelhad *intelhaddata;
	struct snd_pcm_runtime *runtime;
	struct had_pvt_data *had_stream;

	pr_debug("pcm_prepare called\n");

	intelhaddata = snd_pcm_substream_chip(substream);
	runtime = substream->runtime;
	had_stream = intelhaddata->private_data;

	if (had_get_hwstate(intelhaddata)) {
		pr_err("%s: HDMI cable plugged-out\n", __func__);
		snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
		retval = -ENODEV;
		goto prep_end;
	}

	pr_debug("period_size=%d\n",
				frames_to_bytes(runtime, runtime->period_size));
	pr_debug("periods=%d\n", runtime->periods);
	pr_debug("buffer_size=%d\n", snd_pcm_lib_buffer_bytes(substream));
	pr_debug("rate=%d\n", runtime->rate);
	pr_debug("channels=%d\n", runtime->channels);

	if (intelhaddata->stream_info.str_id) {
		pr_debug("_prepare is called for existing str_id#%d\n",
					intelhaddata->stream_info.str_id);
		retval = snd_intelhad_pcm_trigger(substream,
						SNDRV_PCM_TRIGGER_STOP);
		return retval;
	}

	retval = snd_intelhad_init_stream(substream);
	if (retval)
		goto prep_end;


	/* Get N value in KHz */
	retval = had_get_caps(HAD_GET_SAMPLING_FREQ, &disp_samp_freq);
	if (retval) {
		pr_err("querying display sampling freq failed %#x\n", retval);
		goto prep_end;
	}

	had_get_caps(HAD_GET_ELD, &intelhaddata->eeld);

	retval = snd_intelhad_prog_n(substream->runtime->rate, &n_param,
								intelhaddata);
	if (retval) {
		pr_err("programming N value failed %#x\n", retval);
		goto prep_end;
	}
	snd_intelhad_prog_cts(substream->runtime->rate,
					disp_samp_freq, n_param, intelhaddata);

	snd_intelhad_prog_dip(substream, intelhaddata, 0);

	retval = snd_intelhad_init_audio_ctrl(substream, intelhaddata, 0);

	/* Prog buffer address */
	retval = snd_intelhad_prog_buffer(intelhaddata,
			HAD_BUF_TYPE_A, HAD_BUF_TYPE_D);

prep_end:
	return retval;
}
    static void
vaudio_intr_data (void* cookie, NkXIrq xirq)
{
    struct vaudio_stream* s = (struct vaudio_stream*) cookie;
    NkDevRing*   ring   = s->ring;
    nku32_f	 oresp  = s->resp;
    const nku32_f mask   = ring->imask;
    const nku32_f nresp  = ring->iresp;
    bool	 trigger = 0;
#if VAUDIO_PROC_SYNC
    if (vaudio_sync_force_close &&
        s->stream->pcm->device == 0 &&
        s->stream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {
        while (vaudio_send_data(s) >= 0);
        // memset(s->stream->dma_buffer.area, 0, NK_VAUDIO_MAX_RING_SIZE);
        return;
    }
#endif
    (void) xirq;
    if (s->active) {
	struct snd_pcm_runtime* runtime = s->stream->runtime;
	int periods_avail;
	int periods_tosend;

	if (s->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
	    periods_avail = snd_pcm_playback_avail(runtime) /
				    runtime->period_size;
	} else {
	    periods_avail = snd_pcm_capture_avail(runtime) /
				    runtime->period_size;
	}
	DTRACE ("%d %d %d\n",
		s->periods_avail, periods_avail, s->periods_tosend);
	periods_tosend = s->periods_avail - periods_avail;
	if (periods_tosend > 0) {
	    s->periods_tosend += periods_tosend;
	}
	s->periods_avail = periods_avail;
	while (s->periods_tosend) {
	    const int res = vaudio_send_data(s);
	    if (res < 0) break;
	    if (res == 1) trigger = 1;
	    s->periods_tosend--;
	}
    }
    while (oresp != nresp) {
	NkRingDesc*  desc = s->rbase + (oresp & mask);

	if (desc->status == (nku32_f) NK_VAUDIO_STATUS_ERROR) {
	    snd_pcm_stop(s->stream, SNDRV_PCM_STATE_XRUN);
	} else {
	    if (s->active) {
		struct snd_pcm_runtime* runtime = s->stream->runtime;

		s->hwptr_done++;
		s->hwptr_done %= runtime->periods;
		snd_pcm_period_elapsed(s->stream);
		s->periods_avail++;
	    }
	}
	oresp++;
    }
    s->resp = oresp;
    if (trigger) {
	nkops.nk_xirq_trigger(ring->cxirq, s->vaudio->vlink->s_id);
    }
}
Ejemplo n.º 26
0
static void abort_alsa_playback(struct ua101 *ua)
{
	if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states))
		snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN);
}
Ejemplo n.º 27
0
static void abort_alsa_capture(struct ua101 *ua)
{
	if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states))
		snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN);
}
Ejemplo n.º 28
0
int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags)
{
	struct snd_pcm_runtime *runtime = ak4117->substream ? ak4117->substream->runtime : NULL;
	unsigned long _flags;
	int res = 0;
	unsigned char rcs0, rcs1, rcs2;
	unsigned char c0, c1;

	rcs1 = reg_read(ak4117, AK4117_REG_RCS1);
	if (flags & AK4117_CHECK_NO_STAT)
		goto __rate;
	rcs0 = reg_read(ak4117, AK4117_REG_RCS0);
	rcs2 = reg_read(ak4117, AK4117_REG_RCS2);
	// printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2);
	spin_lock_irqsave(&ak4117->lock, _flags);
	if (rcs0 & AK4117_PAR)
		ak4117->parity_errors++;
	if (rcs0 & AK4117_V)
		ak4117->v_bit_errors++;
	if (rcs2 & AK4117_CCRC)
		ak4117->ccrc_errors++;
	if (rcs2 & AK4117_QCRC)
		ak4117->qcrc_errors++;
	c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^
                     (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK));
	c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^
	             (rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f));
	ak4117->rcs0 = rcs0 & ~(AK4117_QINT | AK4117_CINT | AK4117_STC);
	ak4117->rcs1 = rcs1;
	ak4117->rcs2 = rcs2;
	spin_unlock_irqrestore(&ak4117->lock, _flags);

	if (rcs0 & AK4117_PAR)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[0]->id);
	if (rcs0 & AK4117_V)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[1]->id);
	if (rcs2 & AK4117_CCRC)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[2]->id);
	if (rcs2 & AK4117_QCRC)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[3]->id);

	/* rate change */
	if (c1 & 0x0f)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[4]->id);

	if ((c1 & AK4117_PEM) | (c0 & AK4117_CINT))
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[6]->id);
	if (c0 & AK4117_QINT)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[8]->id);

	if (c0 & AK4117_AUDION)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[9]->id);
	if (c1 & AK4117_NPCM)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[10]->id);
	if (c1 & AK4117_DTSCD)
		snd_ctl_notify(ak4117->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4117->kctls[11]->id);
		
	if (ak4117->change_callback && (c0 | c1) != 0)
		ak4117->change_callback(ak4117, c0, c1);

      __rate:
	/* compare rate */
	res = external_rate(rcs1);
	if (!(flags & AK4117_CHECK_NO_RATE) && runtime && runtime->rate != res) {
		snd_pcm_stream_lock_irqsave(ak4117->substream, _flags);
		if (snd_pcm_running(ak4117->substream)) {
			// printk(KERN_DEBUG "rate changed (%i <- %i)\n", runtime->rate, res);
			snd_pcm_stop(ak4117->substream, SNDRV_PCM_STATE_DRAINING);
			wake_up(&runtime->sleep);
			res = 1;
		}
		snd_pcm_stream_unlock_irqrestore(ak4117->substream, _flags);
	}
	return res;
}
static void pcm_afe_process_rx_pkt(uint32_t opcode,
		uint32_t token, uint32_t *payload,
		 void *priv)
{
	struct pcm_afe_info *prtd = priv;
	unsigned long dsp_flags;
	struct snd_pcm_substream *substream = NULL;
	struct snd_pcm_runtime *runtime = NULL;
	uint16_t event;
	uint64_t period_bytes;
	uint64_t bytes_one_sec;

	if (prtd == NULL)
		return;
	substream =  prtd->substream;
	runtime = substream->runtime;
	pr_debug("%s\n", __func__);
	spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
	switch (opcode) {
	case AFE_EVENT_RT_PROXY_PORT_STATUS: {
		event = (uint16_t)((0xFFFF0000 & payload[0]) >> 0x10);
		switch (event) {
		case AFE_EVENT_RTPORT_START: {
			prtd->dsp_cnt = 0;
			/* Calculate poll time. Split steps to avoid overflow.
			 * Poll time-time corresponding to one period in bytes.
			 * (Samplerate * channelcount * format)=bytes in 1 sec.
			 * Poll time =  (period bytes / bytes in one sec) *
			 * 1000000 micro seconds.
			 * Multiplication by 1000000 is done in two steps to
			 * keep the accuracy of poll time.
			 */
			period_bytes = ((uint64_t)(
				(snd_pcm_lib_period_bytes(prtd->substream)) *
				 1000));
			bytes_one_sec = (runtime->rate * runtime->channels * 2);
			bytes_one_sec = div_u64(bytes_one_sec , 1000);
			prtd->poll_time =
				div_u64(period_bytes, bytes_one_sec);
			pr_debug("prtd->poll_time : %d\n", prtd->poll_time);
			break;
		}
		case AFE_EVENT_RTPORT_STOP:
			pr_debug("%s: event!=0\n", __func__);
			prtd->start = 0;
			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
			break;
		case AFE_EVENT_RTPORT_LOW_WM:
			pr_debug("%s: Underrun\n", __func__);
			break;
		case AFE_EVENT_RTPORT_HI_WM:
			pr_debug("%s: Overrun\n", __func__);
			break;
		default:
			break;
		}
		break;
	}
	case APR_BASIC_RSP_RESULT: {
		switch (payload[0]) {
		case AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2:
			pr_debug("Read done\n");
			prtd->pcm_irq_pos += snd_pcm_lib_period_bytes
							(prtd->substream);
			snd_pcm_period_elapsed(prtd->substream);
			break;
		default:
			break;
		}
		break;
	}
	default:
		break;
	}
	spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
}
Ejemplo n.º 30
0
/*
 * uni_player_irq_handler
 * In case of error audio stream is stopped; stop action is protected via PCM
 * stream lock to avoid race condition with trigger callback.
 */
static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
{
	irqreturn_t ret = IRQ_NONE;
	struct uniperif *player = dev_id;
	unsigned int status;
	unsigned int tmp;

	if (player->state == UNIPERIF_STATE_STOPPED) {
		/* Unexpected IRQ: do nothing */
		return IRQ_NONE;
	}

	/* Get interrupt status & clear them immediately */
	status = GET_UNIPERIF_ITS(player);
	SET_UNIPERIF_ITS_BCLR(player, status);

	/* Check for fifo error (underrun) */
	if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(player))) {
		dev_err(player->dev, "FIFO underflow error detected\n");

		/* Interrupt is just for information when underflow recovery */
		if (player->underflow_enabled) {
			/* Update state to underflow */
			player->state = UNIPERIF_STATE_UNDERFLOW;

		} else {
			/* Disable interrupt so doesn't continually fire */
			SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player);

			/* Stop the player */
			snd_pcm_stream_lock(player->substream);
			snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
			snd_pcm_stream_unlock(player->substream);
		}

		ret = IRQ_HANDLED;
	}

	/* Check for dma error (overrun) */
	if (unlikely(status & UNIPERIF_ITS_DMA_ERROR_MASK(player))) {
		dev_err(player->dev, "DMA error detected\n");

		/* Disable interrupt so doesn't continually fire */
		SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player);

		/* Stop the player */
		snd_pcm_stream_lock(player->substream);
		snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock(player->substream);

		ret = IRQ_HANDLED;
	}

	/* Check for underflow recovery done */
	if (unlikely(status & UNIPERIF_ITM_UNDERFLOW_REC_DONE_MASK(player))) {
		if (!player->underflow_enabled) {
			dev_err(player->dev,
				"unexpected Underflow recovering\n");
			return -EPERM;
		}
		/* Read the underflow recovery duration */
		tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player);
		dev_dbg(player->dev, "Underflow recovered (%d LR clocks max)\n",
			tmp);

		/* Clear the underflow recovery duration */
		SET_UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION(player);

		/* Update state to started */
		player->state = UNIPERIF_STATE_STARTED;

		ret = IRQ_HANDLED;
	}

	/* Check if underflow recovery failed */
	if (unlikely(status &
		     UNIPERIF_ITM_UNDERFLOW_REC_FAILED_MASK(player))) {
		dev_err(player->dev, "Underflow recovery failed\n");

		/* Stop the player */
		snd_pcm_stream_lock(player->substream);
		snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
		snd_pcm_stream_unlock(player->substream);

		ret = IRQ_HANDLED;
	}

	return ret;
}