diff options
Diffstat (limited to 'sound/soc/tegra/tegra_pcm.c')
-rw-r--r-- | sound/soc/tegra/tegra_pcm.c | 106 |
1 files changed, 14 insertions, 92 deletions
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 6aea653c2de1..5f413c1216e5 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -23,21 +23,6 @@ #define PLAYBACK_STARTED true #define PLAYBACK_STOPPED false -static void start_i2s_playback(void) -{ - i2s_fifo_set_attention_level(I2S_IFC, I2S_FIFO_TX, - I2S_FIFO_ATN_LVL_FOUR_SLOTS); - i2s_fifo_enable(I2S_IFC, I2S_FIFO_TX, 1); -} - -static void stop_i2s_playback(void) -{ - i2s_set_fifo_irq_on_err(I2S_IFC, I2S_FIFO_TX, 0); - i2s_set_fifo_irq_on_qe(I2S_IFC, I2S_FIFO_TX, 0); - i2s_fifo_enable(I2S_IFC, I2S_FIFO_TX, 0); - while (i2s_get_status(I2S_IFC) & I2S_I2S_FIFO_TX_BUSY); -} - static void tegra_pcm_play(struct tegra_runtime_data *prtd) { static int reqid = 0; @@ -75,51 +60,6 @@ static void tegra_pcm_play(struct tegra_runtime_data *prtd) } -static void dma_tx_complete_callback (struct tegra_dma_req *req) -{ - struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev; - struct snd_pcm_substream *substream = prtd->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (++prtd->period_index >= runtime->periods) { - prtd->period_index = 0; - } - - if (prtd->dma_state != STATE_ABORT) { - snd_pcm_period_elapsed(substream); - tegra_pcm_play(prtd); - } -} - -static void setup_dma_tx_request(struct tegra_dma_req *req) -{ - memset(req, 0, sizeof(*req)); - req->complete = dma_tx_complete_callback; - req->to_memory = false; - req->dest_addr = i2s_get_fifo_phy_base(I2S_IFC, I2S_FIFO_TX); - req->dest_wrap = 4; - req->source_bus_width = 32; - req->source_wrap = 0; - req->dest_bus_width = 32; - req->req_sel = I2S_IFC ? 1 : 2; /* 1 = I2S2, 2 = I2S1 */ -} - -/* recording */ -static void start_i2s_capture(void) -{ - i2s_fifo_set_attention_level(I2S_IFC, I2S_FIFO_RX, - I2S_FIFO_ATN_LVL_FOUR_SLOTS); - i2s_fifo_enable(I2S_IFC, I2S_FIFO_RX, 1); -} - -static void stop_i2s_capture(void) -{ - i2s_set_fifo_irq_on_err(I2S_IFC, I2S_FIFO_RX, 0); - i2s_set_fifo_irq_on_qe(I2S_IFC, I2S_FIFO_RX, 0); - i2s_fifo_enable(I2S_IFC, I2S_FIFO_RX, 0); - while (i2s_get_status(I2S_IFC) & I2S_I2S_FIFO_RX_BUSY); -} - static void tegra_pcm_capture(struct tegra_runtime_data *prtd) { static int reqid = 0; @@ -157,7 +97,7 @@ static void tegra_pcm_capture(struct tegra_runtime_data *prtd) } -static void dma_rx_complete_callback(struct tegra_dma_req *req) +static void dma_complete_callback (struct tegra_dma_req *req) { struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev; struct snd_pcm_substream *substream = prtd->substream; @@ -169,23 +109,14 @@ static void dma_rx_complete_callback(struct tegra_dma_req *req) if (prtd->dma_state != STATE_ABORT) { snd_pcm_period_elapsed(substream); - tegra_pcm_capture(prtd); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + tegra_pcm_play(prtd); + } else { + tegra_pcm_capture(prtd); + } } } -static void setup_dma_rx_request(struct tegra_dma_req *req) -{ - memset(req, 0, sizeof(*req)); - req->complete = dma_rx_complete_callback; - req->to_memory = true; - req->source_addr = i2s_get_fifo_phy_base(I2S_IFC, I2S_FIFO_RX); - req->dest_wrap = 0; - req->source_bus_width = 32; - req->source_wrap = 4; - req->dest_bus_width = 32; - req->req_sel = I2S_IFC ? 1 : 2; /* 1 = I2S2, 2 = I2S1 */ -} - static const struct snd_pcm_hardware tegra_pcm_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | \ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | \ @@ -238,14 +169,12 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) prtd->dma_state = STATE_INIT; tegra_pcm_play(prtd); /* dma enqueue req1 */ tegra_pcm_play(prtd); /* dma enqueue req2 */ - start_i2s_playback(); } else if (prtd->state != STATE_INIT) { /* start recording */ prtd->state = STATE_INIT; prtd->dma_state = STATE_INIT; tegra_pcm_capture(prtd); /* dma enqueue req1 */ tegra_pcm_capture(prtd); /* dma enqueue req2 */ - start_i2s_capture(); } break; case SNDRV_PCM_TRIGGER_STOP: @@ -256,7 +185,6 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) tegra_dma_cancel(prtd->dma_chan); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (prtd->dma_chan) { - stop_i2s_playback(); tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req1); tegra_dma_dequeue_req(prtd->dma_chan, @@ -264,7 +192,6 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) } } else { if (prtd->dma_chan) { - stop_i2s_capture(); tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req1); tegra_dma_dequeue_req(prtd->dma_chan, @@ -337,16 +264,15 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream) prtd->state = STATE_INVALID; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - setup_dma_tx_request(&prtd->dma_req1); - setup_dma_tx_request(&prtd->dma_req2); - } else { - setup_dma_rx_request(&prtd->dma_req1); - setup_dma_rx_request(&prtd->dma_req2); - } + setup_dma_request(substream, + &prtd->dma_req1, + dma_complete_callback, + prtd); - prtd->dma_req1.dev = prtd; - prtd->dma_req2.dev = prtd; + setup_dma_request(substream, + &prtd->dma_req2, + dma_complete_callback, + prtd); prtd->dma_chan = tegra_dma_allocate_channel(TEGRA_DMA_MODE_CONTINUOUS_DOUBLE); if (IS_ERR(prtd->dma_chan)) { @@ -394,10 +320,6 @@ static int tegra_pcm_close(struct snd_pcm_substream *substream) prtd->dma_state = STATE_EXIT; tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req1); tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req2); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - stop_i2s_playback(); - else - stop_i2s_capture(); tegra_dma_flush(prtd->dma_chan); tegra_dma_free_channel(prtd->dma_chan); prtd->dma_chan = NULL; |