int mv88fx_snd_hw_init(struct mv88fx_snd_chip *chip) { /* Clear ints */ cs42l51_init(); mv88fx_snd_writel(chip, MV_AUDIO_INT_CAUSE_REG, 0xffffffff); mv88fx_snd_writel(chip, MV_AUDIO_INT_MASK_REG, 0); mv88fx_snd_writel(chip, MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG, 0); if (MV_OK != mvAudioInit()) return EIO; /* Disable all playback/recording */ mv88fx_snd_bitreset(chip, MV_AUDIO_PLAYBACK_CTRL_REG, (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK)); mv88fx_snd_bitreset(chip, MV_AUDIO_RECORD_CTRL_REG, (ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK)); if (MV_OK != mvSPDIFRecordTclockSet()) { mv88fx_snd_debug("Marvell ALSA driver ERR. mvSPDIFRecordTclockSet failed\n"); return -ENOMEM; } return 0; }
static int mv88fx_i2_hw_init(int port) { mv88fx_snd_debug(""); mv88fx_snd_writel(mv88fx_i2s_info[port].base, MV_AUDIO_INT_CAUSE_REG(port), 0xffffffff); mv88fx_snd_writel(mv88fx_i2s_info[port].base, MV_AUDIO_INT_MASK_REG(port), 0); mv88fx_snd_writel(mv88fx_i2s_info[port].base, MV_AUDIO_SPDIF_REC_INT_CAUSE_MASK_REG(port), 0); // if (MV_OK != mvAudioInit(mv88fx_i2s_info.port)) // return -EIO; mvSysAudioInit(port); /* Disable all playback/recording */ mv88fx_snd_bitreset(mv88fx_i2s_info[port].base, MV_AUDIO_PLAYBACK_CTRL_REG(port), (APCR_PLAY_I2S_ENABLE_MASK | APCR_PLAY_SPDIF_ENABLE_MASK)); mv88fx_snd_bitreset(mv88fx_i2s_info[port].base, MV_AUDIO_RECORD_CTRL_REG(port), (ARCR_RECORD_SPDIF_EN_MASK | ARCR_RECORD_I2S_EN_MASK)); if (MV_OK != mvSPDIFRecordTclockSet(port)) { mv88fx_snd_error("mvSPDIFRecordTclockSet failed"); return -ENOMEM; } return 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; }
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; }