Example #1
0
static int mv88fx_i2s_prepare(struct snd_pcm_substream *substream,
				struct snd_soc_dai *dai)
{
	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip(substream);
	mv88fx_snd_debug("");

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		return mv88fx_i2s_snd_hw_capture_set(chip, substream);
	else
		return mv88fx_i2s_snd_hw_playback_set(chip, substream);

}
Example #2
0
static int mv88fx_snd_ctrl_new(struct snd_card *card)
{
	int err = 0;
	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip();

	playback_src_mixer.rec =
	    &chip->stream[SNDRV_PCM_STREAM_PLAYBACK].dig_mode;
	playback_mono_mixer.rec =
	    &chip->stream[SNDRV_PCM_STREAM_PLAYBACK].mono_mode;

	capture_src_mixer.rec =
	    &chip->stream[SNDRV_PCM_STREAM_CAPTURE].dig_mode;
	capture_mono_mixer.rec =
	    &chip->stream[SNDRV_PCM_STREAM_CAPTURE].mono_mode;

	if (chip->pdata->i2s_play && chip->pdata->spdif_play) {
		err =
		    snd_ctl_add(card,
				snd_ctl_new1(&mv88fx_snd_mixers
					     [PLAYBACK_MIX_INDX], chip));
		if (err < 0)
			return err;
	}

	if (chip->pdata->i2s_play || chip->pdata->spdif_play) {
		err =
		    snd_ctl_add(card,
				snd_ctl_new1(&mv88fx_snd_mixers
					     [PLAYBACK_MONO_MIX_INDX], chip));
		if (err < 0)
			return err;
	}

	if (chip->pdata->i2s_rec && chip->pdata->spdif_rec) {
		err =
		    snd_ctl_add(card,
				snd_ctl_new1(&mv88fx_snd_mixers
					     [CAPTURE_MIX_INDX], chip));
		if (err < 0)
			return err;
	}

	if (chip->pdata->i2s_rec || chip->pdata->spdif_rec) {
		err =
		    snd_ctl_add(card,
				snd_ctl_new1(&mv88fx_snd_mixers
					     [CAPTURE_MONO_MIX_INDX], chip));
		if (err < 0)
			return err;
	}

	if (chip->pdata->spdif_play) {
		err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_mask,
						     chip));
		if (err < 0)
			return err;
	}
	if (chip->pdata->spdif_play) {
		err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_default,
						     chip));
		if (err < 0)
			return err;
	}
	if (chip->pdata->spdif_play) {
		err = snd_ctl_add(card, snd_ctl_new1(&mv88fx_snd_spdif_stream,
						     chip));
		if (err < 0)
			return err;
	}

	return err;
}
Example #3
0
static int mv88fx_i2s_playback_trigger(struct snd_pcm_substream *substream,
				       int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mv88fx_snd_stream *audio_stream = runtime->private_data;
	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip(substream);
	int result = 0;

	mv88fx_snd_debug("substream=%p cmd=%d audio_stream=%p", substream, cmd,
			 audio_stream);

	spin_lock(&chip->reg_lock);
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:

		mv88fx_snd_debug("");
		/* enable interrupt */
		mv88fx_snd_bitset(chip->base, MV_AUDIO_INT_MASK_REG(chip->port),
				  AICR_PLAY_BYTES_INT);

		/* make sure the dma in pause state */
		mv88fx_snd_bitset(chip->base,
			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
			APCR_PLAY_PAUSE_MASK);

		/* enable dma */
		if ((audio_stream->dig_mode & I2S) && (chip->pcm_mode == PCM))
			mv88fx_snd_bitset(chip->base,
				MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
				APCR_PLAY_I2S_ENABLE_MASK);

		if (audio_stream->dig_mode & SPDIF)
			mv88fx_snd_bitset(chip->base,
				MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
				APCR_PLAY_SPDIF_ENABLE_MASK);

		/* start dma */
		mv88fx_snd_bitreset(chip->base,
				    MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
				    APCR_PLAY_PAUSE_MASK);

		break;
	case SNDRV_PCM_TRIGGER_STOP:

		mv88fx_snd_debug("");

		/* disable interrupt */
		mv88fx_snd_bitreset(chip->base,
			MV_AUDIO_INT_MASK_REG(chip->port),
			AICR_PLAY_BYTES_INT);

		/* make sure the dma in pause state */
		mv88fx_snd_bitset(chip->base,
			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
			APCR_PLAY_PAUSE_MASK);

		/* always stop both I2S and SPDIF */
		mv88fx_snd_bitreset(chip->base,
				    MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
				    (APCR_PLAY_I2S_ENABLE_MASK |
				     APCR_PLAY_SPDIF_ENABLE_MASK));

		/* check if busy twice */
		while (mv88fx_snd_readl(chip->base,
			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port)) &
		       APCR_PLAY_BUSY_MASK)
			;

		while (mv88fx_snd_readl(chip->base,
			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port)) &
		       APCR_PLAY_BUSY_MASK)
			;

		break;
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
	case SNDRV_PCM_TRIGGER_SUSPEND:
		mv88fx_snd_debug("");

		mv88fx_snd_bitset(chip->base,
			MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
			APCR_PLAY_PAUSE_MASK);
		break;
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		mv88fx_snd_debug("");

		mv88fx_snd_bitreset(chip->base,
				    MV_AUDIO_PLAYBACK_CTRL_REG(chip->port),
				    APCR_PLAY_PAUSE_MASK);

		break;
	default:
		result = -EINVAL;
		break;
	}
	spin_unlock(&chip->reg_lock);
	mv88fx_snd_debug("result=%d", result);
	return result;
}
Example #4
0
static int mv88fx_i2s_capture_trigger(struct snd_pcm_substream *substream,
				      int cmd)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct mv88fx_snd_stream *audio_stream = runtime->private_data;
	struct mv88fx_snd_chip *chip = mv88fx_pcm_get_chip(substream);
	int result = 0;

	mv88fx_snd_debug("substream=%p cmd=%d audio_stream=%p", substream, cmd,
			 audio_stream);

	spin_lock(&chip->reg_lock);
	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		/* FIXME: should check if busy before */
		mv88fx_snd_debug("");
		/* make sure the dma in pause state */
		mv88fx_snd_bitset(chip->base,
			MV_AUDIO_RECORD_CTRL_REG(chip->port),
			ARCR_RECORD_PAUSE_MASK);

		/* enable interrupt */
		mv88fx_snd_bitset(chip->base, MV_AUDIO_INT_MASK_REG(chip->port),
				  AICR_RECORD_BYTES_INT);

		/* enable dma */
		mv88fx_snd_debug("dig_mode=%x", audio_stream->dig_mode);
		if (audio_stream->dig_mode & I2S) {
			mv88fx_snd_debug("enable dma");
			mv88fx_snd_bitset(chip->base,
					  MV_AUDIO_RECORD_CTRL_REG(chip->port),
					  ARCR_RECORD_I2S_EN_MASK);
		}

		if (audio_stream->dig_mode & SPDIF) {
			mv88fx_snd_debug("enable spdif dma");
			mv88fx_snd_bitset(chip->base,
					  MV_AUDIO_RECORD_CTRL_REG(chip->port),
					  ARCR_RECORD_SPDIF_EN_MASK);
		}

		/* start dma */
		mv88fx_snd_bitreset(chip->base,
			MV_AUDIO_RECORD_CTRL_REG(chip->port),
			ARCR_RECORD_PAUSE_MASK);

		break;
	case SNDRV_PCM_TRIGGER_STOP:

		/* make sure the dma in pause state */
		mv88fx_snd_bitset(chip->base,
			MV_AUDIO_RECORD_CTRL_REG(chip->port),
			ARCR_RECORD_PAUSE_MASK);

		/* disable interrupt */
		mv88fx_snd_bitreset(chip->base,
			MV_AUDIO_INT_MASK_REG(chip->port),
			AICR_RECORD_BYTES_INT);

		/* always stop both I2S and SPDIF */
		mv88fx_snd_bitreset(chip->base,
			MV_AUDIO_RECORD_CTRL_REG(chip->port),
			(ARCR_RECORD_I2S_EN_MASK | ARCR_RECORD_SPDIF_EN_MASK));

		/* FIXME: should check if busy after */

		break;
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
	case SNDRV_PCM_TRIGGER_SUSPEND:
		mv88fx_snd_bitset(chip->base,
			MV_AUDIO_RECORD_CTRL_REG(chip->port),
			ARCR_RECORD_PAUSE_MASK);
		break;
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		mv88fx_snd_bitreset(chip->base,
			MV_AUDIO_RECORD_CTRL_REG(chip->port),
			ARCR_RECORD_PAUSE_MASK);

		break;
	default:
		result = -EINVAL;
		break;
	}
	spin_unlock(&chip->reg_lock);
	mv88fx_snd_debug("result=%d", result);
	return result;
}