示例#1
0
/* trigger callback */
static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
	int err = 0;

	audio_info(" .. IN\n");

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n",
			alsa_stream->running);
		if (!alsa_stream->running) {
			err = bcm2835_audio_start(alsa_stream);
			if (!err) {
				alsa_stream->pcm_indirect.hw_io =
					alsa_stream->pcm_indirect.hw_data =
					bytes_to_frames(runtime,
					alsa_stream->pos);
				substream->ops->ack(substream);
				alsa_stream->running = 1;
				alsa_stream->draining = 1;
			} else {
				audio_error(" Failed to START alsa device (%d)\n", err);
			}
		}
		break;
	case SNDRV_PCM_TRIGGER_STOP:
		audio_debug
			("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n",
			alsa_stream->running, runtime->status->state == SNDRV_PCM_STATE_DRAINING);
		if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
			audio_info("DRAINING\n");
			alsa_stream->draining = 1;
		} else {
			audio_info("DROPPING\n");
			alsa_stream->draining = 0;
		}
		if (alsa_stream->running) {
			err = bcm2835_audio_stop(alsa_stream);
			if (err != 0)
				audio_error(" Failed to STOP alsa device (%d)\n", err);
			alsa_stream->running = 0;
		}
		break;
	default:
		err = -EINVAL;
	}

	audio_info(" .. OUT\n");
	return err;
}
示例#2
0
/******************************************************************************
* function : Ai -> Ao(with fade in/out and volume adjust)
******************************************************************************/
HI_S32 unidoli_audio_service_config(AUDIO_DEV AiDev, AUDIO_DEV AoDev, AUDIO_SAMPLE_RATE_E sample_rast, int num_perfrm)
{
    HI_S32 s32Ret = HI_FAILURE;
    AIO_ATTR_S stAioAttr;

    stAioAttr.enSamplerate   = sample_rast;
    stAioAttr.enBitwidth     = AUDIO_BIT_WIDTH_16;
    stAioAttr.enWorkmode     = AIO_MODE_I2S_MASTER;
    stAioAttr.enSoundmode    = AUDIO_SOUND_MODE_MONO;
    stAioAttr.u32EXFlag      = 0;
    stAioAttr.u32FrmNum      = 30;
    stAioAttr.u32PtNumPerFrm = num_perfrm;
    stAioAttr.u32ChnCnt      = 1;
    stAioAttr.u32ClkSel      = 0;
    
    /* config audio codec */
    /*** INNER AUDIO CODEC ***/
    s32Ret = unidoli_codec_config_audio(stAioAttr.enSamplerate);
    if (HI_SUCCESS != s32Ret)
    {
        printf("%s:SAMPLE_INNER_CODEC_CfgAudio failed\n", __FUNCTION__);
        return s32Ret;
    }
    
    /* enable AI channle */    
    HI_S32 s32AiChnCnt = stAioAttr.u32ChnCnt;
    s32Ret = unidoli_start_ai(AiDev, s32AiChnCnt, &stAioAttr, NULL, 0);
    if (s32Ret != HI_SUCCESS)
    {
        audio_debug(s32Ret);
        return s32Ret;
    }

    HI_S32 s32AoChnCnt = stAioAttr.u32ChnCnt;
    s32Ret = unidoli_start_ao(AoDev, s32AoChnCnt, &stAioAttr, NULL , 0);
    if (s32Ret != HI_SUCCESS)
    {
        audio_debug(s32Ret);
        return s32Ret;
    }

    return s32Ret;
}
示例#3
0
/* prepare callback */
static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
{
	struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
	int channels;
	int err;

	audio_info(" .. IN\n");

	if (mutex_lock_interruptible(&chip->audio_mutex))
		return -EINTR;

	/* notify the vchiq that it should enter spdif passthrough mode by
	 * setting channels=0 (see
	 * https://github.com/raspberrypi/linux/issues/528) */
	if (chip->spdif_status & IEC958_AES0_NONAUDIO)
		channels = 0;
	else
		channels = alsa_stream->channels;

	err = bcm2835_audio_set_params(alsa_stream, channels,
		alsa_stream->params_rate,
		alsa_stream->pcm_format_width);
	if (err < 0) {
		audio_error(" error setting hw params\n");
	}

	bcm2835_audio_setup(alsa_stream);

	/* in preparation of the stream, set the controls (volume level) of the stream */
	bcm2835_audio_set_ctls(alsa_stream->chip);


	memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));

	alsa_stream->pcm_indirect.hw_buffer_size =
		alsa_stream->pcm_indirect.sw_buffer_size =
		snd_pcm_lib_buffer_bytes(substream);

	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);

	mutex_unlock(&chip->audio_mutex);
	audio_info(" .. OUT\n");
	return 0;
}
示例#4
0
/* pointer callback */
static snd_pcm_uframes_t
snd_bcm2835_pcm_pointer(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");

	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 bytes_to_frames(runtime, alsa_stream->pos);
}
示例#5
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;
}
示例#6
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;
}
示例#7
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;
}