Example #1
0
static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
		struct snd_pcm_substream *substream,
		enum dma_transfer_direction direction)
{
	struct dma_chan			*chan;
	struct dw_cyclic_desc		*cdesc;
	struct snd_pcm_runtime		*runtime = substream->runtime;
	unsigned long			buffer_len, period_len;

	/*
	 * We don't do DMA on "complex" transfers, i.e. with
	 * non-halfword-aligned buffers or lengths.
	 */
	if (runtime->dma_addr & 1 || runtime->buffer_size & 1) {
		dev_dbg(&chip->pdev->dev, "too complex transfer\n");
		return -EINVAL;
	}

	if (direction == DMA_MEM_TO_DEV)
		chan = chip->dma.tx_chan;
	else
		chan = chip->dma.rx_chan;

	buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
	period_len = frames_to_bytes(runtime, runtime->period_size);

	cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
			period_len, direction);
	if (IS_ERR(cdesc)) {
		dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n");
		return PTR_ERR(cdesc);
	}

	if (direction == DMA_MEM_TO_DEV) {
		cdesc->period_callback = atmel_ac97c_dma_playback_period_done;
		set_bit(DMA_TX_READY, &chip->flags);
	} else {
		cdesc->period_callback = atmel_ac97c_dma_capture_period_done;
		set_bit(DMA_RX_READY, &chip->flags);
	}

	cdesc->period_callback_param = chip;

	return 0;
}
Example #2
0
/* pointer callback */
static snd_pcm_uframes_t
snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;

	audio_info(" .. IN\n");

	audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0,
		frames_to_bytes(runtime, runtime->status->hw_ptr),
		frames_to_bytes(runtime, runtime->control->appl_ptr),
		alsa_stream->pos);

	audio_info(" .. OUT\n");
	return snd_pcm_indirect_playback_pointer(substream,
		&alsa_stream->pcm_indirect,
		alsa_stream->pos);
}
Example #3
0
int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct tegra_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct tegra_pcm_dma_params * dmap;
	unsigned long flags;
	int i;

	dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
	if (!dmap)
		return 0;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		prtd->dma_pos = 0;
		prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
		prtd->period_index = 0;
		prtd->dma_req_idx = 0;
		if (prtd->disable_intr) {
			prtd->dma_req_count = 1;
			prtd->dma_req[0].complete = NULL;
		} else if (!prtd->dma_req[0].complete) {
			prtd->dma_req[0].complete = dma_complete_callback;
			prtd->dma_req_count =
				(MAX_DMA_REQ_COUNT <= runtime->periods) ?
				MAX_DMA_REQ_COUNT : runtime->periods;
		}
		/* Fall-through */
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 1;
		spin_unlock_irqrestore(&prtd->lock, flags);
		for (i = 0; i < prtd->dma_req_count; i++)
			tegra_pcm_queue_dma(prtd);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 0;
		spin_unlock_irqrestore(&prtd->lock, flags);
		tegra_dma_cancel(prtd->dma_chan);
		for (i = 0; i < prtd->dma_req_count; i++) {
			if (prtd->dma_req[i].complete &&
				(prtd->dma_req[i].status ==
				 -TEGRA_DMA_REQ_ERROR_ABORTED))
				prtd->dma_req[i].complete(&prtd->dma_req[i]);
		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
Example #4
0
static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct tegra_runtime_data *prtd = runtime->private_data;
	unsigned long flags;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		prtd->dma_pos = 0;
		prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
		prtd->period_index = 0;
		prtd->dma_req_idx = 0;
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 1;
#if 0
		if( prtd->dma_chan ){
			prtd->pcm_timeout_tick = jiffies;
			del_timer(&prtd->pcm_timeout);
			prtd->pcm_timeout.function = pcm_timeout_func;
			prtd->pcm_timeout.expires = jiffies + msecs_to_jiffies((runtime->period_size/(runtime->rate/1000))*runtime->periods*2);
			prtd->pcm_timeout.data = (unsigned long)prtd;
			add_timer(&prtd->pcm_timeout);		
			prtd->callback_time = jiffies;
		}
#endif
		spin_unlock_irqrestore(&prtd->lock, flags);
		if( prtd->dma_chan ){
			tegra_pcm_queue_dma(prtd);
			tegra_pcm_queue_dma(prtd);
		}
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		spin_lock_irqsave(&prtd->lock, flags);
		prtd->running = 0;
#if 0
		if( prtd->dma_chan ){
			del_timer(&prtd->pcm_timeout);
		}
#endif
		spin_unlock_irqrestore(&prtd->lock, flags);

		if( prtd->dma_chan ){
			tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]);
			tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]);
		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
static int i2sirx_i2so_mix_copy
(
    struct snd_pcm_substream *substream,
    int channel,
    snd_pcm_uframes_t pos,
    void __user *buf,
    snd_pcm_uframes_t frames
)
{
    __u8 *read_src;
    __u32 size_bytes;
    __u32 offset_bytes;
    
    struct snd_pcm_runtime *runtime = substream->runtime;
        
    if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream)
    {
        printk("%s,%d\n", __FUNCTION__, __LINE__);
    }
    else
    {               
        offset_bytes = frames_to_bytes(runtime, pos);
        read_src = i2sirx_i2so_mix_ring_base_get() + offset_bytes;
        size_bytes = frames_to_bytes(runtime, frames);
        
        /* For debug.
        */
        if (1 == ali_alsa_i2sirx_i2so_mix_out_dump_en_get())
        {
            ali_alsa_dump_data("/data/data/ali_alsa_mix_out_dump.pcm", read_src,
                size_bytes);
        }
        
        if (copy_to_user(buf, read_src, size_bytes))
        {
            printk("%s,%d\n", __FUNCTION__, __LINE__);  
        
            return(-EFAULT);        
        }
    }
    
    return 0;
}
Example #6
0
/*
 * prepare playback/capture channel
 */
static int snd_nm256_pcm_prepare(snd_pcm_substream_t *substream)
{
    nm256_t *chip = snd_pcm_substream_chip(substream);
    snd_pcm_runtime_t *runtime = substream->runtime;
    nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;

    snd_assert(s, return -ENXIO);
    s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size);
    s->period_size = frames_to_bytes(runtime, substream->runtime->period_size);
    s->periods = substream->runtime->periods;
    s->cur_period = 0;

    spin_lock_irq(&chip->reg_lock);
    s->running = 0;
    snd_nm256_set_format(chip, s, substream);
    spin_unlock_irq(&chip->reg_lock);

    return 0;
}
Example #7
0
static void
do_filter_regions (sw_sample * sample, SweepFilterRegion func,
		   sw_param_set pset, gpointer custom_data)
{
  sw_sounddata * sounddata = sample->sounddata;
  sw_format * f = sounddata->format;
  GList * gl;
  sw_sel * sel;
  sw_framecount_t sel_total, run_total;
  sw_framecount_t offset, remaining, n;
  gpointer d;
  gint percent;

  gboolean active = TRUE;

  sel_total = sounddata_selection_nr_frames (sounddata) / 100;
  if (sel_total == 0) sel_total = 1;
  run_total = 0;

  for (gl = sounddata->sels; active && gl; gl = gl->next) {
    sel = (sw_sel *)gl->data;

    offset = 0;
    remaining = sel->sel_end - sel->sel_start;

    while (active && remaining > 0) {
      g_mutex_lock (&sample->ops_mutex);

      if (sample->edit_state == SWEEP_EDIT_STATE_CANCEL) {
	active = FALSE;
      } else {
	d = sounddata->data + (int)frames_to_bytes (f, sel->sel_start + offset);

	n = MIN(remaining, 1024);

	func (d, sounddata->format, n, pset, custom_data);

	remaining -= n;
	offset += n;

	run_total += n;
	percent = run_total / sel_total;
	sample_set_progress_percent (sample, percent);

#ifdef DEBUG
	g_print ("completed %d / %d frames, %d%%\n", run_total, sel_total,
		 percent);
#endif
      }

      g_mutex_unlock (&sample->ops_mutex);
    }
  }
}
Example #8
0
/*
 * prepare playback/capture channel
 */
static int snd_nm256_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct nm256 *chip = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct nm256_stream *s = runtime->private_data;

	if (snd_BUG_ON(!s))
		return -ENXIO;
	s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size);
	s->period_size = frames_to_bytes(runtime, substream->runtime->period_size);
	s->periods = substream->runtime->periods;
	s->cur_period = 0;

	spin_lock_irq(&chip->reg_lock);
	s->running = 0;
	snd_nm256_set_format(chip, s, substream);
	spin_unlock_irq(&chip->reg_lock);

	return 0;
}
Example #9
0
static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev,
			      const struct urb *urb,
			      const struct usb_iso_packet_descriptor *iso)
{
	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
	int stream, i;

	/* paranoia check */
	if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM))
		return;

	for (i = 0; i < iso->actual_length;) {
		for (stream = 0; stream < dev->n_streams; stream++) {
			struct snd_pcm_substream *sub = dev->sub_capture[stream];
			char *audio_buf = NULL;
			int c, n, sz = 0;

			if (sub && !dev->input_panic) {
				struct snd_pcm_runtime *rt = sub->runtime;
				audio_buf = rt->dma_area;
				sz = frames_to_bytes(rt, rt->buffer_size);
			}

			for (c = 0; c < CHANNELS_PER_STREAM; c++) {
				/* 3 audio data bytes, followed by 1 check byte */
				if (audio_buf) {
					for (n = 0; n < BYTES_PER_SAMPLE; n++) {
						audio_buf[dev->audio_in_buf_pos[stream]++] = usb_buf[i+n];

						if (dev->audio_in_buf_pos[stream] == sz)
							dev->audio_in_buf_pos[stream] = 0;
					}

					dev->period_in_count[stream] += BYTES_PER_SAMPLE;
				}

				i += BYTES_PER_SAMPLE;

				if (usb_buf[i] != ((stream << 1) | c) &&
				    !dev->first_packet) {
					if (!dev->input_panic)
						printk(" EXPECTED: %02x got %02x, c %d, stream %d, i %d\n",
							((stream << 1) | c), usb_buf[i], c, stream, i);
					dev->input_panic = 1;
				}

				i++;
			}
		}
	}

	if (dev->first_packet > 0)
		dev->first_packet--;
}
Example #10
0
static int davinci_pcm_copy(struct snd_pcm_substream *substream, int channel,
	snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
{
	struct snd_pcm_runtime *runtime = substream->runtime;

	if (copy_from_user(local_buffer + hwoff, buf,
	    frames_to_bytes(runtime, frames))) {
		printk(KERN_ERR "ERROR COPY_FROM_USER\n");
		return -EFAULT;
	}
	return 0;
}
Example #11
0
static int snd_pcm_silence(snd_pcm_substream_t *substream, int channel, 
                            snd_pcm_uframes_t    pos,       snd_pcm_uframes_t count)
{
        snd_pcm_runtime_t *runtime = substream->runtime;
		unsigned char * TempWriteLevel;
		pcm_hw_t *chip = snd_pcm_substream_chip(substream);
        char *hwbuf;
	int   totalbytes;
    
        if(channel != -1)
                return -EINVAL;
         
        hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos);

	  totalbytes = frames_to_bytes(runtime, count);
	chip->NumberOfBytesCopied += totalbytes;
        snd_pcm_format_set_silence(runtime->format, hwbuf, totalbytes);
                 
        /*Update Write Pointer STAPI WORK */
		DEBUG_PRINT(("Silence \n"));
		DEBUG_PRINT(("Current Write Ptr=%x, Size =%d \n", chip->WritePointer, (count *runtime->channels)));
		TempWriteLevel = chip->WritePointer + (count *runtime->channels);
		if((U32)TempWriteLevel>(runtime->dma_addr +runtime->dma_bytes))
		{
			U32 MaxAllowedWritePointer = (U32)runtime->dma_addr +(U32)runtime->dma_bytes;
			U32 Diff;
			U32 RemainingBytes;
			Diff = (U32)MaxAllowedWritePointer - (U32)chip->WritePointer; 
			RemainingBytes = count *runtime->channels - Diff;
			chip->WritePointer = chip->WritePointer + RemainingBytes;

		}
		else 
		{
			chip->WritePointer = TempWriteLevel; 
		}
		DEBUG_PRINT(("Updated Write Ptr=%x \n", chip->WritePointer));
        return 0;
        
}
Example #12
0
static int saudio_data_trigger_process(struct saudio_stream *stream,
					   struct saudio_msg *msg)
{
	int32_t result = 0;
	struct sblock blk = { 0 };
	struct cmd_common *common = NULL;
	struct snd_pcm_runtime *runtime = stream->substream->runtime;
	ADEBUG();

	if (stream->stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
		stream->periods_avail = snd_pcm_playback_avail(runtime) /
		    runtime->period_size;
	} else {
		stream->periods_avail = snd_pcm_capture_avail(runtime) /
		    runtime->period_size;
	}

	pr_debug("saudio.c:stream->periods_avail is %d,block count is %d",
		 stream->periods_avail, sblock_get_free_count(stream->dst,
							      stream->channel));

	stream->periods_tosend = runtime->periods - stream->periods_avail;

	ADEBUG();

	while (stream->periods_tosend) {

		result = sblock_get(stream->dst, stream->channel, &blk, 0);
		if (result) {
			break;
		}
		stream->last_getblk_count++;
		common = (struct cmd_common *)blk.addr;
		blk.length = frames_to_bytes(runtime, runtime->period_size);
		common->command = SAUDIO_DATA_PCM;
		common->sub_cmd = stream->stream_id;
		common->reserved1 =
		    stream->substream->dma_buffer.addr +
		    stream->period * blk.length;

		sblock_send(stream->dst, stream->channel, &blk);

		stream->period++;
		stream->period = stream->period % runtime->periods;
		stream->periods_tosend--;
	}

	pr_debug(":sblock_getblock_count trigger is %d \n",
		 stream->last_getblk_count);

	return result;
}
Example #13
0
cubeb_resampler_speex::cubeb_resampler_speex(SpeexResamplerState * r,
                                             cubeb_stream * s,
                                             cubeb_stream_params params,
                                             uint32_t out_rate,
                                             cubeb_data_callback cb,
                                             long max_count,
                                             void * ptr)
  : speex_resampler(r)
  , stream(s)
  , stream_params(params)
  , data_callback(cb)
  , user_ptr(ptr)
  , buffer_frame_count(max_count)
  , resampling_ratio(static_cast<float>(params.rate) / out_rate)
  , leftover_frame_size(static_cast<uint32_t>(ceilf(1 / resampling_ratio * 2) + 1))
  , leftover_frame_count(0)
  , leftover_frames_buffer(auto_array<uint8_t>(frames_to_bytes(params, leftover_frame_size)))
  , resampling_src_buffer(auto_array<uint8_t>(frames_to_bytes(params,
        frame_count_at_rate(buffer_frame_count, resampling_ratio))))
{
  assert(r);
}
Example #14
0
static int snd_bcm2835_pcm_copy(struct snd_pcm_substream *substream,
				int channel, snd_pcm_uframes_t pos, void *src,
				snd_pcm_uframes_t count)
{
	int ret;
	struct snd_pcm_runtime *runtime = substream->runtime;
	bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;

	audio_info(" .. IN\n");
	audio_debug("copy.......... (%d) hwptr=%d appl=%d pos=%d\n",
		      frames_to_bytes(runtime, count), frames_to_bytes(runtime,
								       runtime->
								       status->
								       hw_ptr),
		      frames_to_bytes(runtime, runtime->control->appl_ptr),
		      alsa_stream->pos);
	ret =
	    bcm2835_audio_write(alsa_stream, frames_to_bytes(runtime, count),
				src);
	audio_info(" .. OUT\n");
	return ret;
}
Example #15
0
static int loopback_prepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct loopback_pcm *dpcm = runtime->private_data;
	struct loopback_cable *cable = dpcm->cable;
	int bps, salign;

	salign = (snd_pcm_format_width(runtime->format) *
						runtime->channels) / 8;
	bps = salign * runtime->rate;
	if (bps <= 0 || salign <= 0)
		return -EINVAL;

	dpcm->buf_pos = 0;
	dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		
		dpcm->silent_size = dpcm->pcm_buffer_size;
		snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
					   runtime->buffer_size * runtime->channels);
	}

	dpcm->irq_pos = 0;
	dpcm->period_update_pending = 0;
	dpcm->pcm_bps = bps;
	dpcm->pcm_salign = salign;
	dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size);

	mutex_lock(&dpcm->loopback->cable_lock);
	if (!(cable->valid & ~(1 << substream->stream)) ||
            (get_setup(dpcm)->notify &&
	     substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
		params_change(substream);
	cable->valid |= 1 << substream->stream;
	mutex_unlock(&dpcm->loopback->cable_lock);

	return 0;
}
Example #16
0
static snd_pcm_uframes_t snd_card_saudio_pcm_pointer(struct snd_pcm_substream
						     *substream)
{
	const struct snd_saudio *saudio = snd_pcm_substream_chip(substream);
	const int stream_id = substream->pstr->stream;
	const int dev = substream->pcm->device;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct saudio_stream *stream =
	    (struct saudio_stream *)&(saudio->dev_ctrl[dev].stream[stream_id]);
	unsigned int offset;
	offset =
	    stream->hwptr_done * frames_to_bytes(runtime, runtime->period_size);
	return bytes_to_frames(runtime, offset);
}
    static snd_pcm_uframes_t
vaudio_snd_pointer (struct snd_pcm_substream* substream)
{
    const NkVaudio          chip = snd_pcm_substream_chip(substream);
    const int               stream_id = substream->pstr->stream;
    const int               dev = substream->pcm->device;
    struct vaudio_stream*   s = &chip->s[dev][stream_id];
    struct snd_pcm_runtime* runtime = substream->runtime;
    unsigned int            offset;

    ADEBUG();
    offset = s->hwptr_done * frames_to_bytes(runtime, runtime->period_size);
    return bytes_to_frames(runtime, offset);
}
Example #18
0
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 *  Function Name: PcmPlaybackPrepare
 *
 *  Description: Prepare PCM playback device, next call is Trigger or Close
 *
 *------------------------------------------------------------
 */
static int PcmPlaybackPrepare(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	brcm_alsa_chip_t *chip = snd_pcm_substream_chip(substream);
	BRCM_AUDIO_Param_Prepare_t parm_prepare;

	aTrace(LOG_ALSA_INTERFACE, "ALSA-CAPH playback_prepare "
		"stream=%d period=%d period_size=%d,"
		"bufsize=%d start_threshold=%ld stop_threshold=%ld"
		" frame_bits %d rate=%d ch=%d\n",
		substream->number, (int)runtime->periods,
		(int)runtime->period_size, (int)runtime->buffer_size,
		runtime->start_threshold, runtime->stop_threshold,
		runtime->frame_bits, runtime->rate, runtime->channels);

	chip->streamCtl[substream->number].stream_hw_ptr = 0;
	parm_prepare.drv_handle = substream->runtime->private_data;
	parm_prepare.cbParams.pfCallBack = AUDIO_DRIVER_InterruptPeriodCB;
	parm_prepare.cbParams.pPrivateData = (void *)substream;
	parm_prepare.period_count = runtime->periods;
	parm_prepare.period_bytes =
	    frames_to_bytes(runtime, runtime->period_size);
	parm_prepare.buf_param.buf_size = runtime->dma_bytes;
	/*virtual address */
	parm_prepare.buf_param.pBuf = runtime->dma_area;
	/* physical address */
	parm_prepare.buf_param.phy_addr = (UInt32) (runtime->dma_addr);

	aTrace(LOG_ALSA_INTERFACE, "buf_size = %d pBuf=0x%lx phy_addr=0x%x\n",
	       runtime->dma_bytes, (UInt32) runtime->dma_area,
	       runtime->dma_addr);

	parm_prepare.drv_config.sample_rate = runtime->rate;
	parm_prepare.drv_config.num_channel = runtime->channels;
	parm_prepare.drv_config.bits_per_sample = 16;
	parm_prepare.drv_config.instanceId = substream->number;
	parm_prepare.drv_config.arm2sp_mixMode =
	    chip->pi32SpeechMixOption[substream->number];
	parm_prepare.stream = substream->number;

	AUDIO_Ctrl_Trigger(ACTION_AUD_SetPrePareParameters, &parm_prepare, NULL,
			   0);
	/*
	   DEBUG("\n%lx:playback_prepare period bytes=%d,
	   periods =%d, buffersize=%d\n",jiffies,
	   g_brcm_alsa_chip->period_bytes[0], runtime->periods,
	   runtime->dma_bytes);
	 */
	return 0;
}
Example #19
0
static int atmel_abdac_prepare_dma(struct atmel_abdac *dac,
		struct snd_pcm_substream *substream,
		enum dma_data_direction direction)
{
	struct dma_chan			*chan = dac->dma.chan;
	struct dw_cyclic_desc		*cdesc;
	struct snd_pcm_runtime		*runtime = substream->runtime;
	unsigned long			buffer_len, period_len;

	/*
	 * We don't do DMA on "complex" transfers, i.e. with
	 * non-halfword-aligned buffers or lengths.
	 */
	if (runtime->dma_addr & 1 || runtime->buffer_size & 1) {
		dev_dbg(&dac->pdev->dev, "too complex transfer\n");
		return -EINVAL;
	}

	buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
	period_len = frames_to_bytes(runtime, runtime->period_size);

	cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
			period_len, DMA_TO_DEVICE);
	if (IS_ERR(cdesc)) {
		dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n");
		return PTR_ERR(cdesc);
	}

	cdesc->period_callback = atmel_abdac_dma_period_done;
	cdesc->period_callback_param = dac;

	dac->dma.cdesc = cdesc;

	set_bit(DMA_READY, &dac->flags);

	return 0;
}
static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
	int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	unsigned int sample_size = runtime->sample_bits / 8;
	void *buf = runtime->dma_area;
	struct bf5xx_i2s_pcm_data *dma_data;
	unsigned int offset, size;

	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);

	if (dma_data->tdm_mode) {
		offset = pos * 8 * sample_size;
		size = count * 8 * sample_size;
	} else {
		offset = frames_to_bytes(runtime, pos);
		size = frames_to_bytes(runtime, count);
	}

	snd_pcm_format_set_silence(runtime->format, buf + offset, size);

	return 0;
}
Example #21
0
static inline void play_buffer_done (void *arg)
{
	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)arg;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct pcm_runtime_data *prtd = substream->runtime->private_data;
	int size, period_offset, rtbuffersize;

	rtbuffersize = frames_to_bytes(runtime, runtime->buffer_size);
	down(&prtd->buf_done_sem);

	if ((frames_to_bytes(runtime, prtd->cur_pos) +
		TEGRA_DEFAULT_BUFFER_SIZE) > rtbuffersize) {
		size = rtbuffersize -
			frames_to_bytes(runtime, prtd->cur_pos);
	} else {
		size = TEGRA_DEFAULT_BUFFER_SIZE;
	}

	prtd->cur_pos += bytes_to_frames(runtime, size);

	if (prtd->cur_pos < prtd->last_pos) {
		period_offset = (runtime->buffer_size +
				prtd->cur_pos) - prtd->last_pos;
	} else {
		period_offset = prtd->cur_pos - prtd->last_pos;
	}

	if (period_offset >= runtime->period_size) {
		prtd->last_pos = prtd->cur_pos;
		snd_pcm_period_elapsed(substream);
	}

	if (prtd->cur_pos >= runtime->buffer_size) {
		prtd->cur_pos -= runtime->buffer_size;
	}
}
Example #22
0
int PcmPlaybackSilence(struct snd_pcm_substream *substream, int channel,
	       snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos);
	snd_pcm_format_set_silence(runtime->format, hwbuf,
		count * runtime->channels);
	/**
	 * Set DMA engine ready bit according to pos and count
	 */

	aTrace(LOG_ALSA_INTERFACE, "%s: stream = %d, Called\n",
			__func__, substream->number);

	return 0;
}
Example #23
0
static irqreturn_t mxs_pcm_dma_irq(int irq, void *dev_id)
{
	struct snd_pcm_substream *substream = dev_id;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mxs_runtime_data *prtd = substream->runtime->private_data;
	struct mxs_dma_info dma_info;
	void *pdma;
	unsigned long prev_appl_offset, appl_count, cont, appl_ptr_bytes;

	mxs_dma_get_info(prtd->dma_ch, &dma_info);

	if (dma_info.status) {
		printk(KERN_WARNING "%s: DMA audio channel %d (%s) error\n",
			__func__, prtd->params->dma_ch, prtd->params->name);
		mxs_dma_ack_irq(prtd->dma_ch);
	} else {
		if ((prtd->params->dma_ch == MXS_DMA_CHANNEL_AHB_APBX_SPDIF) &&
		    (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
		    (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) &&
		    ((prtd->format == SNDRV_PCM_FORMAT_S24_LE)
		     || (prtd->format == SNDRV_PCM_FORMAT_S20_3LE))) {

			appl_ptr_bytes =
			    frames_to_bytes(runtime,
					    runtime->control->appl_ptr);

			appl_count = appl_ptr_bytes - prtd->appl_ptr_bytes;
			prev_appl_offset =
			    prtd->appl_ptr_bytes % prtd->dma_totsize;
			cont = prtd->dma_totsize - prev_appl_offset;

			if (appl_count > cont) {
				pdma = runtime->dma_area + prev_appl_offset;
				memmove(pdma + 1, pdma, cont - 1);
				pdma = runtime->dma_area;
				memmove(pdma + 1, pdma, appl_count - cont - 1);
			} else {
				pdma = runtime->dma_area + prev_appl_offset;
				memmove(pdma + 1, pdma, appl_count - 1);
			}
			prtd->appl_ptr_bytes = appl_ptr_bytes;
		}
		mxs_dma_ack_irq(prtd->dma_ch);
		snd_pcm_period_elapsed(substream);
	}
	return IRQ_HANDLED;
}
Example #24
0
/* prepare playback callback */
static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
{
	emu10k1_t *emu = snd_pcm_substream_chip(substream);
	snd_pcm_runtime_t *runtime = substream->runtime;
	int channel = substream->pcm->device - emu->p16v_device_offset;
	u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
	u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
	int i;
	u32 tmp;
	
        //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
        //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
	//snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes);
	tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
        switch (runtime->rate) {
	case 44100:
	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
	  break;
	case 96000:
	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
	  break;
	case 192000:
	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
	  break;
	case 48000:
	default:
	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
	  break;
	}
	/* FIXME: Check emu->buffer.size before actually writing to it. */
	for(i=0; i < runtime->periods; i++) {
		table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
		table_base[(i*2)+1]=period_size_bytes<<16;
	}
 
	snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
	snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
	snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
	snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
	//snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
	snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
	snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
	snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
	snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);

	return 0;
}
Example #25
0
static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data)
{
	struct hsw_pcm_data *pcm_data = data;
	struct snd_pcm_substream *substream = pcm_data->substream;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	u32 pos;

	pos = frames_to_bytes(runtime,
		(runtime->control->appl_ptr % runtime->buffer_size));

	dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos);

	/* let alsa know we have play a period */
	snd_pcm_period_elapsed(substream);
	return pos;
}
Example #26
0
static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct hsw_priv_data *pdata =
		snd_soc_platform_get_drvdata(rtd->platform);
	struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd);
	struct sst_hsw *hsw = pdata->hsw;
	snd_pcm_uframes_t offset;

	offset = bytes_to_frames(runtime,
		sst_hsw_get_dsp_position(hsw, pcm_data->stream));

	dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n",
		frames_to_bytes(runtime, (u32)offset));
	return offset;
}
Example #27
0
static void audio_dma_irq(void *data)
{
	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mxc_runtime_data *prtd = runtime->private_data;

	prtd->dma_active = 0;
	prtd->periods++;
	prtd->periods %= runtime->periods;

	dbg("irq per %d offset %x\n", prtd->periods,
	    frames_to_bytes(runtime, runtime->period_size) * prtd->periods);

	if (prtd->active)
		snd_pcm_period_elapsed(substream);
	dma_new_period(substream);
}
Example #28
0
static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
			      const struct urb *urb,
			      const struct usb_iso_packet_descriptor *iso)
{
	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
	unsigned char check_byte;
	struct snd_pcm_substream *sub;
	int stream, i;

	for (i = 0; i < iso->actual_length;) {
		if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
			for (stream = 0;
			     stream < dev->n_streams;
			     stream++, i++) {
				if (dev->first_packet)
					continue;

				check_byte = MAKE_CHECKBYTE(dev, stream, i);

				if ((usb_buf[i] & 0x3f) != check_byte)
					dev->input_panic = 1;

				if (usb_buf[i] & 0x80)
					dev->output_panic = 1;
			}
		}
		dev->first_packet = 0;

		for (stream = 0; stream < dev->n_streams; stream++, i++) {
			sub = dev->sub_capture[stream];
			if (dev->input_panic)
				usb_buf[i] = 0;

			if (sub) {
				struct snd_pcm_runtime *rt = sub->runtime;
				char *audio_buf = rt->dma_area;
				int sz = frames_to_bytes(rt, rt->buffer_size);
				audio_buf[dev->audio_in_buf_pos[stream]++] =
					usb_buf[i];
				dev->period_in_count[stream]++;
				if (dev->audio_in_buf_pos[stream] == sz)
					dev->audio_in_buf_pos[stream] = 0;
			}
		}
	}
}
Example #29
0
static int dma_new_period(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mxc_runtime_data *prtd = runtime->private_data;
	unsigned int dma_size = frames_to_bytes(runtime, runtime->period_size);
	unsigned int offset = dma_size * prtd->period;
	int ret = 0;
	mxc_dma_requestbuf_t sdma_request;

	if (!prtd->active)
		return 0;

	memset(&sdma_request, 0, sizeof(mxc_dma_requestbuf_t));

	dbg("period pos  ALSA %x DMA %x\n", runtime->periods, prtd->period);
	dbg("period size ALSA %x DMA %x Offset %x dmasize %x\n",
	    (unsigned int)runtime->period_size,
	    runtime->dma_bytes, offset, dma_size);
	dbg("DMA addr %x\n", runtime->dma_addr + offset);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		sdma_request.src_addr =
		    (dma_addr_t) (runtime->dma_addr + offset);
	else
		sdma_request.dst_addr =
		    (dma_addr_t) (runtime->dma_addr + offset);

	sdma_request.num_of_bytes = dma_size;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		mxc_dma_config(prtd->dma_wchannel,
			       &sdma_request, 1, MXC_DMA_MODE_WRITE);
		ret = mxc_dma_enable(prtd->dma_wchannel);
	} else {

		mxc_dma_config(prtd->dma_wchannel,
			       &sdma_request, 1, MXC_DMA_MODE_READ);
		ret = mxc_dma_enable(prtd->dma_wchannel);
	}
	prtd->dma_active = 1;
	prtd->period++;
	prtd->period %= runtime->periods;

	return ret;
}
Example #30
0
static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id)
{
	bcm2835_alsa_stream_t *alsa_stream = (bcm2835_alsa_stream_t *) dev_id;
	uint32_t consumed = 0;
	int new_period = 0;

	audio_info(" .. IN\n");

	audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
		   alsa_stream ? alsa_stream->substream : 0);

	if (alsa_stream->open)
		consumed = bcm2835_audio_retrieve_buffers(alsa_stream);

	/* We get called only if playback was triggered, So, the number of buffers we retrieve in
	 * each iteration are the buffers that have been played out already
	 */

	if (alsa_stream->period_size) {
		if ((alsa_stream->pos / alsa_stream->period_size) !=
		    ((alsa_stream->pos + consumed) / alsa_stream->period_size))
			new_period = 1;
	}
	audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n",
		      alsa_stream->pos,
		      consumed,
		      alsa_stream->buffer_size,
			  (int)(alsa_stream->period_size*alsa_stream->substream->runtime->periods),
			  frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr),
			  new_period);
	if (alsa_stream->buffer_size) {
		alsa_stream->pos += consumed &~ (1<<30);
		alsa_stream->pos %= alsa_stream->buffer_size;
	}

	if (alsa_stream->substream) {
		if (new_period)
			snd_pcm_period_elapsed(alsa_stream->substream);
	} else {
		audio_warning(" unexpected NULL substream\n");
	}
	audio_info(" .. OUT\n");

	return IRQ_HANDLED;
}