MV_VOID mvAudioSpcrCtrlGet(int unit, MV_AUDIO_FREQ_DATA *spcrCtrl) { MV_U32 reg = MV_REG_READ(MV_AUDIO_SPCR_DCO_STATUS_REG(unit)); spcrCtrl->baseFreq = (reg & ASDSR_SPCR_CTRLFS_MASK) >> ASDSR_SPCR_CTRLFS_OFFS ; spcrCtrl->offset = (reg & ASDSR_SPCR_CTRLOFFSET_MASK) >> ASDSR_SPCR_CTRLOFFSET_OFFS; }
static int mv88fx_i2s_snd_hw_playback_set(struct mv88fx_snd_chip *chip, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct mv88fx_snd_stream *audio_stream = runtime->private_data; MV_AUDIO_PLAYBACK_CTRL pcm_play_ctrl; MV_I2S_PLAYBACK_CTRL i2s_play_ctrl; MV_SPDIF_PLAYBACK_CTRL spdif_play_ctrl; MV_AUDIO_FREQ_DATA dco_ctrl; mv88fx_snd_debug("chip=%p chip->base=%p", chip, chip->base); memset(&pcm_play_ctrl, 0, sizeof(pcm_play_ctrl)); memset(&dco_ctrl, 0, sizeof(dco_ctrl)); memset(&i2s_play_ctrl, 0, sizeof(i2s_play_ctrl)); memset(&spdif_play_ctrl, 0, sizeof(spdif_play_ctrl)); dco_ctrl.offset = chip->dco_ctrl_offst; mv88fx_snd_debug("rate: %u ", runtime->rate); switch (runtime->rate) { case 44100: dco_ctrl.baseFreq = AUDIO_FREQ_44_1KH; break; case 48000: dco_ctrl.baseFreq = AUDIO_FREQ_48KH; break; case 96000: dco_ctrl.baseFreq = AUDIO_FREQ_96KH; break; default: mv88fx_snd_error("Requested rate %d is not supported", runtime->rate); return -1; } pcm_play_ctrl.burst = (chip->burst == 128) ? AUDIO_128BYTE_BURST : AUDIO_32BYTE_BURST; pcm_play_ctrl.loopBack = chip->loopback; if (mv88fx_pcm_is_stereo(runtime)) { pcm_play_ctrl.monoMode = AUDIO_PLAY_MONO_OFF; } else { switch (audio_stream->mono_mode) { case MONO_LEFT: pcm_play_ctrl.monoMode = AUDIO_PLAY_LEFT_MONO; break; case MONO_RIGHT: pcm_play_ctrl.monoMode = AUDIO_PLAY_RIGHT_MONO; break; case MONO_BOTH: default: pcm_play_ctrl.monoMode = AUDIO_PLAY_BOTH_MONO; break; } } if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) { pcm_play_ctrl.sampleSize = SAMPLE_16BIT; i2s_play_ctrl.sampleSize = SAMPLE_16BIT; } else if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) { pcm_play_ctrl.sampleSize = SAMPLE_24BIT; i2s_play_ctrl.sampleSize = SAMPLE_24BIT; } else if (runtime->format == SNDRV_PCM_FORMAT_S32_LE) { pcm_play_ctrl.sampleSize = SAMPLE_32BIT; i2s_play_ctrl.sampleSize = SAMPLE_32BIT; } else { mv88fx_snd_error("Requested format %d is not supported", runtime->format); return -1; } /* buffer and period sizes in frame */ pcm_play_ctrl.bufferPhyBase = runtime->dma_addr; pcm_play_ctrl.bufferSize = frames_to_bytes(runtime, runtime->buffer_size); pcm_play_ctrl.intByteCount = frames_to_bytes(runtime, runtime->period_size); /* I2S playback streem stuff */ /*i2s_play_ctrl.sampleSize = pcm_play_ctrl.sampleSize; */ i2s_play_ctrl.justification = I2S_JUSTIFIED; i2s_play_ctrl.sendLastFrame = 0; spdif_play_ctrl.nonPcm = MV_FALSE; spdif_play_ctrl.validity = chip->ch_stat_valid; if (audio_stream->stat_mem) { spdif_play_ctrl.userBitsFromMemory = MV_TRUE; spdif_play_ctrl.validityFromMemory = MV_TRUE; spdif_play_ctrl.blockStartInternally = MV_FALSE; } else { spdif_play_ctrl.userBitsFromMemory = MV_FALSE; spdif_play_ctrl.validityFromMemory = MV_FALSE; spdif_play_ctrl.blockStartInternally = MV_TRUE; } mv88fx_snd_debug(""); /* If this is non-PCM sound, mute I2S channel */ spin_lock_irq(&chip->reg_lock); mv88fx_snd_debug("chip=%p chip->base=%p port=%d", chip, chip->base, chip->port); if (!(mv88fx_snd_readl(chip->base, MV_AUDIO_PLAYBACK_CTRL_REG(chip->port)) & (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK))) { mv88fx_snd_debug(""); if (MV_OK != mvAudioDCOCtrlSet(chip->port, &dco_ctrl)) { mv88fx_snd_error ("Failed to initialize DCO clock control."); return -1; mv88fx_snd_debug(""); } } mv88fx_snd_debug(""); if (audio_stream->clock_src == DCO_CLOCK) while ((mv88fx_snd_readl(chip->base, MV_AUDIO_SPCR_DCO_STATUS_REG(chip->port)) & ASDSR_DCO_LOCK_MASK) == 0) ; else if (audio_stream->clock_src == SPCR_CLOCK) while ((mv88fx_snd_readl(chip->base, MV_AUDIO_SPCR_DCO_STATUS_REG(chip->port)) & ASDSR_SPCR_LOCK_MASK) == 0) ; mv88fx_snd_debug(""); if (MV_OK != mvAudioPlaybackControlSet(chip->port, &pcm_play_ctrl)) { mv88fx_snd_error("Failed to initialize PCM playback control."); return -1; } mv88fx_snd_debug(""); if (MV_OK != mvI2SPlaybackCtrlSet(chip->port, &i2s_play_ctrl)) { mv88fx_snd_error("Failed to initialize I2S playback control."); return -1; } mv88fx_snd_debug(""); mvSPDIFPlaybackCtrlSet(chip->port, &spdif_play_ctrl); mv88fx_snd_debug(""); spin_unlock_irq(&chip->reg_lock); return 0; }