/* * 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; }
/* * 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); }
/** * 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); } }
/* 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); } }
/* * 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); }
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); } }
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); }
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); } }
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); }
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); } }
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; }
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); }
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; }
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; }
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; }
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); } }
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; }
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); } }
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; }
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); }
/** * 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); } }
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); }
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); }
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); }
/* * 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; }