- card->dma_start_vaddr[SND_PS3_CH_R] =
- runtime->dma_area + (runtime->dma_bytes / 2);
- card->dma_start_bus_addr[SND_PS3_CH_R] =
- runtime->dma_addr + (runtime->dma_bytes / 2);
-
- pr_debug("%s: vaddr=%p bus=%#lx\n", __func__,
- card->dma_start_vaddr[SND_PS3_CH_L],
- card->dma_start_bus_addr[SND_PS3_CH_L]);
-
- }
- spin_unlock_irqrestore(&card->dma_lock, irqsave);
-
- /* ensure the hardware sees the change */
- mb();
-
- return 0;
-};
-
-static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- /* clear outstanding interrupts */
- update_reg(PS3_AUDIO_AX_IS, 0);
-
- spin_lock(&card->dma_lock);
- {
- card->running = 1;
- }
- spin_unlock(&card->dma_lock);
-
- snd_ps3_program_dma(card,
- SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL);
- snd_ps3_kick_dma(card);
- while (read_reg(PS3_AUDIO_KICK(7)) &
- PS3_AUDIO_KICK_STATUS_MASK) {
- udelay(1);
- }
- snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_RUNNING);
- snd_ps3_kick_dma(card);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- spin_lock(&card->dma_lock);
- {
- card->running = 0;
- }
- spin_unlock(&card->dma_lock);
- snd_ps3_wait_for_dma_stop(card);
- break;
- default:
- break;
-
- }
-
- return ret;
-};
-
-/*
- * report current pointer
- */
-static snd_pcm_uframes_t snd_ps3_pcm_pointer(
- struct snd_pcm_substream *substream)
-{
- struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
- size_t bytes;
- snd_pcm_uframes_t ret;
-
- spin_lock(&card->dma_lock);
- {
- bytes = (size_t)(card->dma_last_transfer_vaddr[SND_PS3_CH_L] -
- card->dma_start_vaddr[SND_PS3_CH_L]);
- }
- spin_unlock(&card->dma_lock);
-
- ret = bytes_to_frames(substream->runtime, bytes * 2);
-
- return ret;
-};
-
-static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- int ret;
- ret = snd_pcm_lib_free_pages(substream);
- return ret;
-};
-
-static int snd_ps3_pcm_close(struct snd_pcm_substream *substream)
-{
- /* mute on */
- snd_ps3_mute(1);
- return 0;
-};
-
-static void snd_ps3_audio_fixup(struct snd_ps3_card_info *card)
-{
- /*
- * avsetting driver seems to never change the followings
- * so, init them here once
- */
-
- /* no dma interrupt needed */
- write_reg(PS3_AUDIO_INTR_EN_0, 0);
-
- /* use every 4 buffer empty interrupt */
- update_mask_reg(PS3_AUDIO_AX_IC,
- PS3_AUDIO_AX_IC_AASOIMD_MASK,
- PS3_AUDIO_AX_IC_AASOIMD_EVERY4);
-
- /* enable 3wire clocks */
- update_mask_reg(PS3_AUDIO_AO_3WMCTRL,
- ~(PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED |
- PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED),
- 0);
- update_reg(PS3_AUDIO_AO_3WMCTRL,
- PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT);
-}
-
-/*
- * av setting
- * NOTE: calling this function may generate audio interrupt.
- */
-static int snd_ps3_change_avsetting(struct snd_ps3_card_info *card)
-{
- int ret, retries, i;
- pr_debug("%s: start\n", __func__);
-
- ret = ps3av_set_audio_mode(card->avs.avs_audio_ch,
- card->avs.avs_audio_rate,
- card->avs.avs_audio_width,
- card->avs.avs_audio_format,
- card->avs.avs_audio_source);
- /*
- * Reset the following unwanted settings:
- */
-
- /* disable all 3wire buffers */
- update_mask_reg(PS3_AUDIO_AO_3WMCTRL,
- ~(PS3_AUDIO_AO_3WMCTRL_ASOEN(0) |
- PS3_AUDIO_AO_3WMCTRL_ASOEN(1) |
- PS3_AUDIO_AO_3WMCTRL_ASOEN(2) |
- PS3_AUDIO_AO_3WMCTRL_ASOEN(3)),
- 0);
- wmb(); /* ensure the hardware sees the change */
- /* wait for actually stopped */
- retries = 1000;
- while ((read_reg(PS3_AUDIO_AO_3WMCTRL) &
- (PS3_AUDIO_AO_3WMCTRL_ASORUN(0) |
- PS3_AUDIO_AO_3WMCTRL_ASORUN(1) |
- PS3_AUDIO_AO_3WMCTRL_ASORUN(2) |
- PS3_AUDIO_AO_3WMCTRL_ASORUN(3))) &&
- --retries) {
- udelay(1);
- }
-
- /* reset buffer pointer */
- for (i = 0; i < 4; i++) {
- update_reg(PS3_AUDIO_AO_3WCTRL(i),
- PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET);
- udelay(10);
- }
- wmb(); /* ensure the hardware actually start resetting */
-
- /* enable 3wire#0 buffer */
- update_reg(PS3_AUDIO_AO_3WMCTRL, PS3_AUDIO_AO_3WMCTRL_ASOEN(0));
-
-
- /* In 24bit mode,ALSA inserts a zero byte at first byte of per sample */
- update_mask_reg(PS3_AUDIO_AO_3WCTRL(0),
- ~PS3_AUDIO_AO_3WCTRL_ASODF,
- PS3_AUDIO_AO_3WCTRL_ASODF_LSB);
- update_mask_reg(PS3_AUDIO_AO_SPDCTRL(0),
- ~PS3_AUDIO_AO_SPDCTRL_SPODF,
- PS3_AUDIO_AO_SPDCTRL_SPODF_LSB);
- /* ensure all the setting above is written back to register */
- wmb();
- /* avsetting driver altered AX_IE, caller must reset it if you want */
- pr_debug("%s: end\n", __func__);
- return ret;
-}