Exemple #1
0
static int lola_pcm_prepare(struct snd_pcm_substream *substream)
{
    struct lola *chip = snd_pcm_substream_chip(substream);
    struct lola_pcm *pcm = lola_get_pcm(substream);
    struct lola_stream *str = lola_get_stream(substream);
    struct snd_pcm_runtime *runtime = substream->runtime;
    unsigned int bufsize, period_bytes, format_verb;
    int i, err;

    mutex_lock(&chip->open_mutex);
    lola_stream_reset(chip, str);
    lola_cleanup_slave_streams(pcm, str);
    if (str->index + runtime->channels > pcm->num_streams) {
        mutex_unlock(&chip->open_mutex);
        return -EINVAL;
    }
    for (i = 1; i < runtime->channels; i++) {
        str[i].master = str;
        str[i].opened = 1;
    }
    mutex_unlock(&chip->open_mutex);

    bufsize = snd_pcm_lib_buffer_bytes(substream);
    period_bytes = snd_pcm_lib_period_bytes(substream);
    format_verb = lola_get_format_verb(substream);

    str->bufsize = bufsize;
    str->period_bytes = period_bytes;
    str->format_verb = format_verb;

    err = lola_setup_periods(chip, pcm, substream, str);
    if (err < 0)
        return err;

    err = lola_set_sample_rate(chip, runtime->rate);
    if (err < 0)
        return err;
    chip->sample_rate = runtime->rate;	/* sample rate gets locked */

    err = lola_set_stream_config(chip, str, runtime->channels);
    if (err < 0)
        return err;

    err = lola_setup_controller(chip, pcm, str);
    if (err < 0) {
        lola_stream_reset(chip, str);
        return err;
    }

    return 0;
}
static enum hrtimer_restart afe_hrtimer_rec_callback(struct hrtimer *hrt)
{
	struct pcm_afe_info *prtd =
		container_of(hrt, struct pcm_afe_info, hrt);
	struct snd_pcm_substream *substream = prtd->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (prtd->start) {
		if (prtd->dsp_cnt == runtime->periods)
			prtd->dsp_cnt = 0;
		afe_rt_proxy_port_read(
			(prtd->dma_addr + (prtd->dsp_cnt
			* snd_pcm_lib_period_bytes(prtd->substream))),
			snd_pcm_lib_period_bytes(prtd->substream));
		prtd->dsp_cnt++;
		pr_debug("sending frame rec to DSP: poll_time: %d\n",
				prtd->poll_time);
		hrtimer_forward_now(hrt, ns_to_ktime(prtd->poll_time
				* 1000));

		return HRTIMER_RESTART;
	} else
		return HRTIMER_NORESTART;
}
Exemple #3
0
static int
snd_ad1889_playback_prepare(struct snd_pcm_substream *ss)
{
	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
	struct snd_pcm_runtime *rt = ss->runtime;
	unsigned int size = snd_pcm_lib_buffer_bytes(ss);
	unsigned int count = snd_pcm_lib_period_bytes(ss);
	u16 reg;

	ad1889_channel_reset(chip, AD_CHAN_WAV);

	reg = ad1889_readw(chip, AD_DS_WSMC);
	
	/* Mask out 16-bit / Stereo */
	reg &= ~(AD_DS_WSMC_WA16 | AD_DS_WSMC_WAST);

	if (snd_pcm_format_width(rt->format) == 16)
		reg |= AD_DS_WSMC_WA16;

	if (rt->channels > 1)
		reg |= AD_DS_WSMC_WAST;

	/* let's make sure we don't clobber ourselves */
	spin_lock_irq(&chip->lock);
	
	chip->wave.size = size;
	chip->wave.reg = reg;
	chip->wave.addr = rt->dma_addr;

	ad1889_writew(chip, AD_DS_WSMC, chip->wave.reg);
	
	/* Set sample rates on the codec */
	ad1889_writew(chip, AD_DS_WAS, rt->rate);

	/* Set up DMA */
	ad1889_load_wave_buffer_address(chip, chip->wave.addr);
	ad1889_load_wave_buffer_count(chip, size);
	ad1889_load_wave_interrupt_count(chip, count);

	/* writes flush */
	ad1889_readw(chip, AD_DS_WSMC);
	
	spin_unlock_irq(&chip->lock);
	
	ad1889_debug("prepare playback: addr = 0x%x, count = %u, "
			"size = %u, reg = 0x%x, rate = %u\n", chip->wave.addr,
			count, size, reg, rt->rate);
	return 0;
}
static enum hrtimer_restart afe_hrtimer_rec_callback(struct hrtimer *hrt)
{
	struct pcm_afe_info *prtd =
		container_of(hrt, struct pcm_afe_info, hrt);
	struct snd_pcm_substream *substream = prtd->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;
	u32 mem_map_handle = 0;
	int ret;

	mem_map_handle = afe_req_mmap_handle(prtd->audio_client);
	if (!mem_map_handle)
		pr_err("%s: mem_map_handle is NULL\n", __func__);

	if (prtd->start) {
		if (prtd->dsp_cnt == runtime->periods)
			prtd->dsp_cnt = 0;
		pr_debug("%s: mem_map_handle 0x%x\n", __func__, mem_map_handle);
		ret = afe_rt_proxy_port_read(
		(prtd->dma_addr + (prtd->dsp_cnt
		* snd_pcm_lib_period_bytes(prtd->substream))), mem_map_handle,
		snd_pcm_lib_period_bytes(prtd->substream));
		if (ret < 0) {
			pr_err("%s: AFE port read fails: %d\n", __func__, ret);
			prtd->start = 0;
			return HRTIMER_NORESTART;
		}
		prtd->dsp_cnt++;
		pr_debug("sending frame rec to DSP: poll_time: %d\n",
				prtd->poll_time);
		hrtimer_forward_now(hrt, ns_to_ktime(prtd->poll_time
				* 1000));

		return HRTIMER_RESTART;
	} else
		return HRTIMER_NORESTART;
}
int msm_pcm_mmap(struct snd_pcm_substream *substream,
				struct vm_area_struct *vma)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct msm_audio *prtd = runtime->private_data;

	prtd->out_head = 0; /* point to First buffer on startup */
	prtd->mmap_flag = 1;
	runtime->dma_bytes = snd_pcm_lib_period_bytes(substream)*2;
	dma_mmap_coherent(substream->pcm->card->dev, vma,
				     runtime->dma_area,
				     runtime->dma_addr,
				     runtime->dma_bytes);
	return 0;
}
Exemple #6
0
static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct msm_audio *prtd = runtime->private_data;
	struct audmgr_config cfg;
	int rc;

	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
	prtd->pcm_irq_pos = 0;
	prtd->pcm_buf_pos = 0;

	/* rate and channels are sent to audio driver */
	prtd->samp_rate = convert_samp_rate(runtime->rate);
	prtd->samp_rate_index = convert_dsp_samp_index(runtime->rate);
	prtd->channel_mode = (runtime->channels - 1);
	prtd->buffer_size = prtd->channel_mode ? STEREO_DATA_SIZE : \
							MONO_DATA_SIZE;

	if (prtd->enabled == 1)
		return 0;

	prtd->type = AUDREC_CMD_TYPE_0_INDEX_WAV;

	cfg.tx_rate = convert_samp_rate(runtime->rate);
	cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
	cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
	cfg.codec = RPC_AUD_DEF_CODEC_PCM;
	cfg.snd_method = RPC_SND_METHOD_MIDI;

	rc = audmgr_enable(&prtd->audmgr, &cfg);
	if (rc < 0)
		return rc;

	if (msm_adsp_enable(prtd->audpre)) {
		audmgr_disable(&prtd->audmgr);
		return -ENODEV;
	}
	if (msm_adsp_enable(prtd->audrec)) {
		msm_adsp_disable(prtd->audpre);
		audmgr_disable(&prtd->audmgr);
		return -ENODEV;
	}
	prtd->enabled = 1;
	alsa_rec_dsp_enable(prtd, 1);

	return 0;
}
Exemple #7
0
static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct msm_audio *prtd = runtime->private_data;

	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
	prtd->pcm_irq_pos = 0;
	prtd->pcm_buf_pos = 0;

	/* rate and channels are sent to audio driver */
	prtd->out_sample_rate = runtime->rate;
	prtd->out_channel_mode = runtime->channels;

	return 0;
}
Exemple #8
0
static int
snd_ad1889_capture_prepare(struct snd_pcm_substream *ss)
{
	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
	struct snd_pcm_runtime *rt = ss->runtime;
	unsigned int size = snd_pcm_lib_buffer_bytes(ss);
	unsigned int count = snd_pcm_lib_period_bytes(ss);
	u16 reg;

	ad1889_channel_reset(chip, AD_CHAN_ADC);
	
	reg = ad1889_readw(chip, AD_DS_RAMC);

	/* Mask out 16-bit / Stereo */
	reg &= ~(AD_DS_RAMC_AD16 | AD_DS_RAMC_ADST);

	if (snd_pcm_format_width(rt->format) == 16)
		reg |= AD_DS_RAMC_AD16;

	if (rt->channels > 1)
		reg |= AD_DS_RAMC_ADST;

	/* let's make sure we don't clobber ourselves */
	spin_lock_irq(&chip->lock);
	
	chip->ramc.size = size;
	chip->ramc.reg = reg;
	chip->ramc.addr = rt->dma_addr;

	ad1889_writew(chip, AD_DS_RAMC, chip->ramc.reg);

	/* Set up DMA */
	ad1889_load_adc_buffer_address(chip, chip->ramc.addr);
	ad1889_load_adc_buffer_count(chip, size);
	ad1889_load_adc_interrupt_count(chip, count);

	/* writes flush */
	ad1889_readw(chip, AD_DS_RAMC);
	
	spin_unlock_irq(&chip->lock);
	
	dev_dbg(chip->card->dev,
		"prepare capture: addr = 0x%x, count = %u, size = %u, reg = 0x%x, rate = %u\n",
		chip->ramc.addr, count, size, reg, rt->rate);
	return 0;
}
static void msm_pcm_enqueue_data(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct msm_audio *prtd = runtime->private_data;
	unsigned int period_size;

	pr_debug("prtd->out_tail =%d mmap_flag=%d\n",
			prtd->out_tail, prtd->mmap_flag);
	period_size = snd_pcm_lib_period_bytes(substream);
	alsa_dsp_send_buffer(prtd, prtd->out_tail, period_size);
	prtd->out_tail ^= 1;
	++copy_count;
	prtd->period++;
	if (unlikely(prtd->period >= runtime->periods))
		prtd->period = 0;

}
static int
snd_ad1889_capture_prepare(struct snd_pcm_substream *ss)
{
	struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
	struct snd_pcm_runtime *rt = ss->runtime;
	unsigned int size = snd_pcm_lib_buffer_bytes(ss);
	unsigned int count = snd_pcm_lib_period_bytes(ss);
	u16 reg;

	ad1889_channel_reset(chip, AD_CHAN_ADC);
	
	reg = ad1889_readw(chip, AD_DS_RAMC);

	
	reg &= ~(AD_DS_RAMC_AD16 | AD_DS_RAMC_ADST);

	if (snd_pcm_format_width(rt->format) == 16)
		reg |= AD_DS_RAMC_AD16;

	if (rt->channels > 1)
		reg |= AD_DS_RAMC_ADST;

	
	spin_lock_irq(&chip->lock);
	
	chip->ramc.size = size;
	chip->ramc.reg = reg;
	chip->ramc.addr = rt->dma_addr;

	ad1889_writew(chip, AD_DS_RAMC, chip->ramc.reg);

	
	ad1889_load_adc_buffer_address(chip, chip->ramc.addr);
	ad1889_load_adc_buffer_count(chip, size);
	ad1889_load_adc_interrupt_count(chip, count);

	
	ad1889_readw(chip, AD_DS_RAMC);
	
	spin_unlock_irq(&chip->lock);
	
	ad1889_debug("prepare capture: addr = 0x%x, count = %u, "
			"size = %u, reg = 0x%x, rate = %u\n", chip->ramc.addr,
			count, size, reg, rt->rate);
	return 0;
}
static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
{
	struct davinci_runtime_data *prtd = substream->runtime->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	int lch = prtd->slave_lch;
	unsigned int period_size;
	unsigned int dma_offset;
	dma_addr_t dma_pos;
	dma_addr_t src, dst;
	unsigned short src_bidx, dst_bidx;
	unsigned int data_type;
	unsigned int count;

	period_size = snd_pcm_lib_period_bytes(substream);
	dma_offset = prtd->period * period_size;
	dma_pos = runtime->dma_addr + dma_offset;

	pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
		"dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size);

	data_type = prtd->params->data_type;
	count = period_size / data_type;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		src = dma_pos;
		dst = prtd->params->dma_addr;
		src_bidx = data_type;
		dst_bidx = 0;
	} else {
		src = prtd->params->dma_addr;
		dst = dma_pos;
		src_bidx = 0;
		dst_bidx = data_type;
	}

	davinci_set_dma_src_params(lch, src, INCR, W8BIT);
	davinci_set_dma_dest_params(lch, dst, INCR, W8BIT);
	davinci_set_dma_src_index(lch, src_bidx, 0);
	davinci_set_dma_dest_index(lch, dst_bidx, 0);
	davinci_set_dma_transfer_params(lch, data_type, count, 1, 0, ASYNC);

	prtd->period++;
	if (unlikely(prtd->period >= runtime->periods))
		prtd->period = 0;
}
/* prepare callback */
static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;

	audio_info(" .. IN\n");

	alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
	alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
	alsa_stream->pos = 0;

	audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
		      alsa_stream->buffer_size, alsa_stream->period_size,
		      alsa_stream->pos, runtime->frame_bits);

	audio_info(" .. OUT\n");
	return 0;
}
Exemple #13
0
static int omap_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	struct omap_pcm_dma_data *dma_data = prtd->dma_data;
	struct omap_dma_channel_params dma_params;

	memset(&dma_params, 0, sizeof(dma_params));
	/*
	 * Note: Regardless of interface data formats supported by OMAP McBSP
	 * or EAC blocks, internal representation is always fixed 16-bit/sample
	 */
	dma_params.data_type			= OMAP_DMA_DATA_TYPE_S16;
	dma_params.trigger			= dma_data->dma_req;
	dma_params.sync_mode			= OMAP_DMA_SYNC_ELEMENT;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		dma_params.src_amode		= OMAP_DMA_AMODE_POST_INC;
		dma_params.dst_amode		= OMAP_DMA_AMODE_CONSTANT;
		dma_params.src_or_dst_synch	= OMAP_DMA_DST_SYNC;
		dma_params.src_start		= runtime->dma_addr;
		dma_params.dst_start		= dma_data->port_addr;
		dma_params.dst_port		= OMAP_DMA_PORT_MPUI;
	} else {
		dma_params.src_amode		= OMAP_DMA_AMODE_CONSTANT;
		dma_params.dst_amode		= OMAP_DMA_AMODE_POST_INC;
		dma_params.src_or_dst_synch	= OMAP_DMA_SRC_SYNC;
		dma_params.src_start		= dma_data->port_addr;
		dma_params.dst_start		= runtime->dma_addr;
		dma_params.src_port		= OMAP_DMA_PORT_MPUI;
	}
	/*
	 * Set DMA transfer frame size equal to ALSA period size and frame
	 * count as no. of ALSA periods. Then with DMA frame interrupt enabled,
	 * we can transfer the whole ALSA buffer with single DMA transfer but
	 * still can get an interrupt at each period bounary
	 */
	dma_params.elem_count	= snd_pcm_lib_period_bytes(substream) / 2;
	dma_params.frame_count	= runtime->periods;
	omap_set_dma_params(prtd->dma_ch, &dma_params);

	omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);

	return 0;
}
Exemple #14
0
static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_dummy_pcm *dpcm = runtime->private_data;
	unsigned int bps;

	bps = runtime->rate * runtime->channels;
	bps *= snd_pcm_format_width(runtime->format);
	bps /= 8;
	if (bps <= 0)
		return -EINVAL;
	dpcm->pcm_bps = bps;
	dpcm->pcm_jiffie = bps / HZ;
	dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
	dpcm->pcm_count = snd_pcm_lib_period_bytes(substream);
	dpcm->pcm_irq_pos = 0;
	dpcm->pcm_buf_pos = 0;
	return 0;
}
Exemple #15
0
static int ipq_pcm_mi2s_prepare(struct snd_pcm_substream *substream)
{
	int ret;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct dai_dma_params dma_params;
	struct ipq_lpass_runtime_data_t *prtd =
		(struct ipq_lpass_runtime_data_t *)runtime->private_data;

	if (!prtd) {
		pr_err("%s %d:Error in getting runtime data\n",
						__func__, __LINE__);
		return -EINVAL;
	}

	/*
	 * This is the case for under\over-run, we have already
	 * configured the DMA registers for this stream
	 */
	if (prtd->pcm_stream_info.pcm_prepare_start)
		return 0;

	ipq_lpaif_dma_stop(prtd->lpaif_info.dma_ch);
	prtd->pcm_stream_info.pcm_prepare_start = 1;
	prtd->lpaif_info.lpa_if_dma_start = 0;

	memset(&dma_params, 0, sizeof(dma_params));
	dma_params.src_start = runtime->dma_addr;
	dma_params.buffer_size = snd_pcm_lib_buffer_bytes(substream);
	dma_params.period_size = snd_pcm_lib_period_bytes(substream);
	dma_params.channels = runtime->channels;
	ret = ipq_lpaif_cfg_dma(prtd->lpaif_info.dma_ch, &dma_params,
					prtd->pcm_stream_info.bit_width,
					1 /*enable intr*/);
	if (ret)
		return -EINVAL;

	ipq_lpaif_register_dma_irq_handler(prtd->lpaif_info.dma_ch,
					ipq_mi2s_irq, (void *)substream);

	return 0;
}
static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
{
	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
	struct dma_chan *chan = prtd->dma_chan;
	struct dma_async_tx_descriptor *desc;
	enum dma_transfer_direction direction;
	unsigned long flags = DMA_CTRL_ACK;

	direction = snd_pcm_substream_to_dma_direction(substream);

	if (!substream->runtime->no_period_wakeup)
		flags |= DMA_PREP_INTERRUPT;

	prtd->pos = 0;
	desc = dmaengine_prep_dma_cyclic(chan,
		substream->runtime->dma_addr,
		snd_pcm_lib_buffer_bytes(substream),
		snd_pcm_lib_period_bytes(substream), direction, flags);

	if (!desc)
		return -ENOMEM;

	desc->callback = dmaengine_pcm_dma_complete;
	desc->callback_param = substream;
	prtd->cookie = dmaengine_submit(desc);

#ifdef CONFIG_SND_PXA_SSP_DUMP
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
			&& ssp_playback_enable) {
		prtd->playback_totsize = snd_pcm_lib_buffer_bytes(substream);
		prtd->playback_transfer_addr = substream->runtime->dma_addr;
		prtd->playback_dump_addr = substream->runtime->dma_addr;
	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE
			&& ssp_capture_enable) {
		prtd->capture_totsize = snd_pcm_lib_buffer_bytes(substream);
		prtd->capture_transfer_addr = substream->runtime->dma_addr;
		prtd->capture_dump_addr = substream->runtime->dma_addr;
	}
#endif
	return 0;
}
Exemple #17
0
static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_dummy_pcm *dpcm = runtime->private_data;
	int bps;

	bps = snd_pcm_format_width(runtime->format) * runtime->rate * runtime->channels / 8;

	if (bps <= 0)
		return -EINVAL;

	dpcm->pcm_bps = bps;
	dpcm->pcm_hz = HZ;
	dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
	dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
	dpcm->pcm_irq_pos = 0;
	dpcm->pcm_buf_pos = 0;
	snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));

	return 0;
}
Exemple #18
0
static void pcsp_pointer_update(struct snd_pcsp *chip)
{
	struct snd_pcm_substream *substream;
	size_t period_bytes, buffer_bytes;
	int periods_elapsed;
	unsigned long flags;

	/* update the playback position */
	substream = chip->playback_substream;
	if (!substream)
		return;

	period_bytes = snd_pcm_lib_period_bytes(substream);
	buffer_bytes = snd_pcm_lib_buffer_bytes(substream);

	spin_lock_irqsave(&chip->substream_lock, flags);
	chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size;
	periods_elapsed = chip->playback_ptr - chip->period_ptr;
	if (periods_elapsed < 0) {
#if PCSP_DEBUG
		printk(KERN_INFO "PCSP: buffer_bytes mod period_bytes != 0 ? "
			"(%zi %zi %zi)\n",
			chip->playback_ptr, period_bytes, buffer_bytes);
#endif
		periods_elapsed += buffer_bytes;
	}
	periods_elapsed /= period_bytes;
	/* wrap the pointer _before_ calling snd_pcm_period_elapsed(),
	 * or ALSA will BUG on us. */
	chip->playback_ptr %= buffer_bytes;

	if (periods_elapsed) {
		chip->period_ptr += periods_elapsed * period_bytes;
		chip->period_ptr %= buffer_bytes;
	}
	spin_unlock_irqrestore(&chip->substream_lock, flags);

	if (periods_elapsed)
		tasklet_schedule(&pcsp_pcm_tasklet);
}
Exemple #19
0
static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev,
				      struct snd_pcm_substream **subs)
{
	int stream, pb, *cnt;
	struct snd_pcm_substream *sub;

	for (stream = 0; stream < dev->n_streams; stream++) {
		sub = subs[stream];
		if (!sub)
			continue;

		pb = snd_pcm_lib_period_bytes(sub);
		cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
					&dev->period_out_count[stream] :
					&dev->period_in_count[stream];

		if (*cnt >= pb) {
			snd_pcm_period_elapsed(sub);
			*cnt %= pb;
		}
	}
}
/* Lock me. */
static inline char *bcm947xx_from_linear(struct snd_pcm_substream *substream, snd_pcm_uframes_t pos)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct bcm947xx_runtime_data *brtd = runtime->private_data;
	unsigned int slot;
	unsigned int extrabytes;
	char *hwbuf;

	/* Current slot (0-index). */
	slot = pos / runtime->period_size;

	/* Extra bytes in descriptor (header + unused). */
	extrabytes = BCM947XX_DMA_DATA_BYTES_MAX - snd_pcm_lib_period_bytes(substream);

	/* Calculate DMA buffer position by adding the unused
	 * and header offset bytes. */
	hwbuf = runtime->dma_area +				/* base offset */
		slot * extrabytes +					/* all per slot extra up before current slot */
		frames_to_bytes(runtime, pos) +		/* position in slot */
		brtd->dma_ofs;						/* header offset in current slot */

	return hwbuf;
}
Exemple #21
0
static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream)
{
	u16 current_ptr;
	struct snd_als300 *chip = snd_pcm_substream_chip(substream);
	struct snd_als300_substream_data *data;
	unsigned short period_bytes;

	data = substream->runtime->private_data;
	period_bytes = snd_pcm_lib_period_bytes(substream);
	
	spin_lock(&chip->reg_lock);
	current_ptr = (u16) snd_als300_gcr_read(chip->port,
					data->block_counter_register) + 4;
	spin_unlock(&chip->reg_lock);
	if (current_ptr > period_bytes)
		current_ptr = 0;
	else
		current_ptr = period_bytes - current_ptr;

	if (data->period_flipflop == 0)
		current_ptr += period_bytes;
	snd_als300_dbgplay("Pointer (bytes): %d\n", current_ptr);
	return bytes_to_frames(substream->runtime, current_ptr);
}
static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct msm_audio *prtd = runtime->private_data;

	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
	prtd->pcm_irq_pos = 0;
	prtd->pcm_buf_pos = 0;

	/* rate and channels are sent to audio driver */
	prtd->out_sample_rate = runtime->rate;
	prtd->out_channel_mode = runtime->channels;

	if (prtd->enabled | !(prtd->mmap_flag))
		return 0;

	prtd->data = substream->dma_buffer.area;
	prtd->phys = substream->dma_buffer.addr;
	prtd->out[0].data = prtd->data + 0;
	prtd->out[0].addr = prtd->phys + 0;
	prtd->out[0].size = BUFSZ;
	prtd->out[1].data = prtd->data + BUFSZ;
	prtd->out[1].addr = prtd->phys + BUFSZ;
	prtd->out[1].size = BUFSZ;

	prtd->out[0].used = prtd->pcm_count;
	prtd->out[1].used = prtd->pcm_count;

	mutex_lock(&the_locks.lock);
	alsa_audio_configure(prtd);
	mutex_unlock(&the_locks.lock);


	return 0;
}
static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
{
	struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
	struct dma_chan *chan = prtd->dma_chan;
	struct dma_async_tx_descriptor *desc;
	enum dma_transfer_direction direction;

	direction = snd_pcm_substream_to_dma_direction(substream);

	prtd->pos = 0;
	desc = dmaengine_prep_dma_cyclic(chan,
		substream->runtime->dma_addr,
		snd_pcm_lib_buffer_bytes(substream),
		snd_pcm_lib_period_bytes(substream), direction);

	if (!desc)
		return -ENOMEM;

	desc->callback = dmaengine_pcm_dma_complete;
	desc->callback_param = substream;
	prtd->cookie = dmaengine_submit(desc);

	return 0;
}
static void dmaengine_pcm_dma_complete(void *arg)
{
	struct snd_pcm_substream *substream = NULL;
	struct dmaengine_pcm_runtime_data *prtd = NULL;
	unsigned long flags;

	substream = arg;
	if (!substream) {
		return;
	}
	snd_pcm_stream_lock_irqsave(substream, flags);
	if (!substream->runtime) {
		snd_pcm_stream_unlock_irqrestore(substream, flags);
		return;
	}
	prtd = substream_to_prtd(substream);

	prtd->pos += snd_pcm_lib_period_bytes(substream);
	if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
		prtd->pos = 0;
	snd_pcm_stream_unlock_irqrestore(substream, flags);

	snd_pcm_period_elapsed(substream);
}
Exemple #25
0
		if (rate > 23000) {
			chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
			break;
		}
		/* fallthru */
	case SB_HW_20:
		chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
		break;
	case SB_HW_10:
		chip->playback_format = SB_DSP_OUTPUT;
		break;
	default:
		return -EINVAL;
	}
	size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
	count = chip->p_period_size = snd_pcm_lib_period_bytes(substream);
	spin_lock_irqsave(&chip->reg_lock, flags);
	snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON);
	if (runtime->channels > 1) {
		/* set playback stereo mode */
		spin_lock(&chip->mixer_lock);
		mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW);
		snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02);
		spin_unlock(&chip->mixer_lock);

		/* Soundblaster hardware programming reference guide, 3-23 */
		snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT);
		runtime->dma_area[0] = 0x80;
		snd_dma_program(chip->dma8, runtime->dma_addr, 1, DMA_MODE_WRITE);
		/* force interrupt */
		chip->mode = SB_MODE_HALT;
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);
}
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);
}
static int omap_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct omap_runtime_data *prtd = runtime->private_data;
	struct omap_pcm_dma_data *dma_data = prtd->dma_data;
	struct omap_dma_channel_params dma_params;
	int bytes;

	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
	if (!prtd->dma_data)
		return 0;

	memset(&dma_params, 0, sizeof(dma_params));
	dma_params.data_type			= dma_data->data_type;
	dma_params.trigger			= dma_data->dma_req;
	dma_params.sync_mode			= dma_data->sync_mode;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		dma_params.src_amode		= OMAP_DMA_AMODE_POST_INC;
		dma_params.dst_amode		= OMAP_DMA_AMODE_CONSTANT;
		dma_params.src_or_dst_synch	= OMAP_DMA_DST_SYNC;
		dma_params.src_start		= runtime->dma_addr;
		dma_params.dst_start		= dma_data->port_addr;
		dma_params.dst_port		= OMAP_DMA_PORT_MPUI;
		dma_params.dst_fi		= dma_data->packet_size;
	} else {
		dma_params.src_amode		= OMAP_DMA_AMODE_CONSTANT;
		dma_params.dst_amode		= OMAP_DMA_AMODE_POST_INC;
		dma_params.src_or_dst_synch	= OMAP_DMA_SRC_SYNC;
		dma_params.src_start		= dma_data->port_addr;
		dma_params.dst_start		= runtime->dma_addr;
		dma_params.src_port		= OMAP_DMA_PORT_MPUI;
		dma_params.src_fi		= dma_data->packet_size;
	}
	/*
	 * Set DMA transfer frame size equal to ALSA period size and frame
	 * count as no. of ALSA periods. Then with DMA frame interrupt enabled,
	 * we can transfer the whole ALSA buffer with single DMA transfer but
	 * still can get an interrupt at each period bounary
	 */
	bytes = snd_pcm_lib_period_bytes(substream);
	dma_params.elem_count	= bytes >> dma_data->data_type;
	dma_params.frame_count	= runtime->periods;
	omap_set_dma_params(prtd->dma_ch, &dma_params);

	if ((cpu_is_omap1510()))
		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
			      OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
	else if (!substream->runtime->no_period_wakeup)
		omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
	else {
		/*
		 * No period wakeup:
		 * we need to disable BLOCK_IRQ, which is enabled by the omap
		 * dma core at request dma time.
		 */
		omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ);
	}

	if (!(cpu_class_is_omap1())) {
		omap_set_dma_src_burst_mode(prtd->dma_ch,
						OMAP_DMA_DATA_BURST_16);
		omap_set_dma_dest_burst_mode(prtd->dma_ch,
						OMAP_DMA_DATA_BURST_16);
	}

	return 0;
}
Exemple #29
0
/*
 * Not used with ping/pong
 */
static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
{
	struct davinci_runtime_data *prtd = substream->runtime->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	int link = prtd->asp_link[0];
	unsigned int period_size;
	unsigned int dma_offset;
	dma_addr_t dma_pos;
	dma_addr_t src, dst;
	unsigned short src_bidx, dst_bidx;
	unsigned short src_cidx, dst_cidx;
	unsigned int data_type;
	unsigned short acnt;
	unsigned int count;
	unsigned int fifo_level;

	period_size = snd_pcm_lib_period_bytes(substream);
	dma_offset = prtd->period * period_size;
	dma_pos = runtime->dma_addr + dma_offset;
	fifo_level = prtd->params->fifo_level;

	pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
		"dma_ptr = %x period_size=%x\n", link, dma_pos, period_size);

	data_type = prtd->params->data_type;
	count = period_size / data_type;
	if (fifo_level)
		count /= fifo_level;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		src = dma_pos;
		dst = prtd->params->dma_addr;
		src_bidx = data_type;
		dst_bidx = 0;
		src_cidx = data_type * fifo_level;
		dst_cidx = 0;
	} else {
		src = prtd->params->dma_addr;
		dst = dma_pos;
		src_bidx = 0;
		dst_bidx = data_type;
		src_cidx = 0;
		dst_cidx = data_type * fifo_level;
	}

	acnt = prtd->params->acnt;
	edma_set_src(link, src, INCR, W8BIT);
	edma_set_dest(link, dst, INCR, W8BIT);

	edma_set_src_index(link, src_bidx, src_cidx);
	edma_set_dest_index(link, dst_bidx, dst_cidx);

	if (!fifo_level)
		edma_set_transfer_params(link, acnt, count, 1, 0, ASYNC);
	else
		edma_set_transfer_params(link, acnt, fifo_level, count,
							fifo_level, ABSYNC);

	prtd->period++;
	if (unlikely(prtd->period >= runtime->periods))
		prtd->period = 0;
}
Exemple #30
0
static irqreturn_t
socle_snd_isr(int irq_no, struct snd_soc_dai *soc_dai)
{
	u32 int_stat;
	u32  *buf;
	struct snd_dma_buffer *dma_buffer;
	
	int_stat = socle_i2s_reg_read(SOCLE_I2S_ISR);
//printk("Entered %s int_stat 0x%08X\n", __func__, int_stat);

	/* Check wether is is the rx fifo overrun interrupt*/
	if (int_stat & SOCLE_I2S_RX_FIFO_OVR_INT) {
printk("rx overrun\n");		
		/* Clear the rx fifo */
		socle_i2s_reg_write(
				socle_i2s_reg_read(SOCLE_I2S_RXCTL) |
				SOCLE_I2S_RX_FIFO_CLR,SOCLE_I2S_RXCTL);

		/* Disable the interrupt */
		socle_i2s_reg_write(
				socle_i2s_reg_read(SOCLE_I2S_IER) &
				~(SOCLE_I2S_RX_FIFO_TRIG_INT_EN |
				  SOCLE_I2S_RX_FIFO_OVR_INT_EN),SOCLE_I2S_IER);

		/* Stop the rx transmission */
		socle_i2s_reg_write(
				socle_i2s_conf |
				(socle_i2s_reg_read(SOCLE_I2S_OPR) & SOCLE_I2S_TX_OP_STR),SOCLE_I2S_OPR);

		goto out;
	}

	/* Check whether it is the tx fifo data trigger interrupt */
	if (int_stat & SOCLE_I2S_TX_FIFO_TRIG_INT) {
//printk("%s:		playback_substream %x\n", __func__, (u32)playback_substream);
		dma_buffer = &(playback_substream->dma_buffer);
#if 0
		while ((socle_i2s_reg_read(SOCLE_I2S_FIFOSTS) & SOCLE_I2S_TX_FIFO_FULL) != SOCLE_I2S_TX_FIFO_FULL) {
			buf = (u32 *) &(dma_buffer->area[playback_buf_pos]);
			socle_i2s_reg_write(	*buf, SOCLE_I2S_TXR);
			playback_buf_pos += 4;
			playback_buf_period_pos +=4;
		}
		playback_buf_pos %= dma_buffer->bytes;
		if( playback_buf_period_pos > playback_substream->runtime->period_size) {
//printk("period_size 0x%08X, buf_size 0x%08X\n",(u32) playback_substream->runtime->period_size, dma_buffer->bytes);
			playback_buf_period_pos %= playback_substream->runtime->period_size;
			snd_pcm_period_elapsed(playback_substream);
		}
#else
//printk("dma_buffer->area %x\n", (u32)dma_buffer->area);
		while ((socle_i2s_reg_read(SOCLE_I2S_FIFOSTS) & SOCLE_I2S_TX_FIFO_FULL) != SOCLE_I2S_TX_FIFO_FULL) {
			buf = (u32 *) &(dma_buffer->area[playback_buf_pos]);
			socle_i2s_reg_write(	*buf, SOCLE_I2S_TXR);
			playback_buf_pos += 4;
			playback_buf_pos %= dma_buffer->bytes;
			if( playback_buf_pos % snd_pcm_lib_period_bytes(playback_substream) == 0) {
//printk("%s: playback_buf_pos 0x%08X\n", __func__, playback_buf_pos);
				snd_pcm_period_elapsed(playback_substream);
			}
		}
#endif
	}

	/* Check whether it is the rx fifo data trigger interrupt */
	if (int_stat & SOCLE_I2S_RX_FIFO_TRIG_INT) {
		dma_buffer = &(capture_substream->dma_buffer);
		while ((socle_i2s_reg_read(SOCLE_I2S_FIFOSTS) & SOCLE_I2S_RX_FIFO_EMPTY) != SOCLE_I2S_RX_FIFO_EMPTY) {
			buf = (u32 *) &(dma_buffer->area[capture_buf_pos]);
			*buf = socle_i2s_reg_read(SOCLE_I2S_RXR);
			capture_buf_pos += 4;
			capture_buf_pos %= dma_buffer->bytes;
			if( capture_buf_pos % snd_pcm_lib_period_bytes(capture_substream) == 0) {
				snd_pcm_period_elapsed(capture_substream);
			}
		}
	}
out:
//printk("Exit %s\n", __func__);
	return IRQ_HANDLED;
}