ASOC: Tegra: Fix Tegra20 BT SCO playback/record
Sumit Bhattacharya [Mon, 20 Feb 2012 13:23:23 +0000 (18:23 +0530)]
Set I2s FIFO attention level based on sample size and channel count.
Also set playback DMA destination bus width and capture DMA source bus
width based on sample size. These changes are needed to have proper
BT SCO playback and record which uses 16bit-mono format.

Bug 934101
Bug 874428
Bug 927978

Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com>
Reviewed-on: http://git-master/r/84817
(cherry picked from commit 3ca2eb665af450d7e8f3bf6f2471e31203052641)

Change-Id: I95c10716eaa990adb8b6ae535ce6acfca122a609
Reviewed-on: http://git-master/r/87192
Tested-by: Sumit Bhattacharya <sumitb@nvidia.com>
Reviewed-by: Scott Peterson <speterson@nvidia.com>

sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra_pcm.c

index c868230..9ebe367 100644 (file)
@@ -249,9 +249,14 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
 
        tegra20_i2s_write(i2s, TEGRA20_I2S_TIMING, reg);
 
-       tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR,
-               TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
-               TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
+       if (sample_size * params_channels(params) >= 32)
+               tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR,
+                       TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
+                       TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
+       else
+               tegra20_i2s_write(i2s, TEGRA20_I2S_FIFO_SCR,
+                       TEGRA20_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS |
+                       TEGRA20_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS);
 
        i2s->reg_ctrl &= ~TEGRA20_I2S_CTRL_FIFO_FORMAT_MASK;
        reg = tegra20_i2s_read(i2s, TEGRA20_I2S_PCM_CTRL);
@@ -263,12 +268,17 @@ static int tegra20_i2s_hw_params(struct snd_pcm_substream *substream,
                else
                        i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO_FORMAT_32;
 
+               i2s->capture_dma_data.width = sample_size;
+               i2s->playback_dma_data.width = sample_size;
+
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        reg |= TEGRA20_I2S_PCM_CTRL_TRM_MODE_EN;
                else
                        reg |= TEGRA20_I2S_PCM_CTRL_RCV_MODE_EN;
        } else {
                i2s->reg_ctrl |= TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;
+               i2s->capture_dma_data.width = 32;
+               i2s->playback_dma_data.width = 32;
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                        reg &= ~TEGRA20_I2S_PCM_CTRL_TRM_MODE_EN;
                else
index 3eab18c..f277d28 100644 (file)
@@ -150,14 +150,6 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
        dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        if (dmap) {
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       setup_dma_tx_request(&prtd->dma_req[0], dmap);
-                       setup_dma_tx_request(&prtd->dma_req[1], dmap);
-               } else {
-                       setup_dma_rx_request(&prtd->dma_req[0], dmap);
-                       setup_dma_rx_request(&prtd->dma_req[1], dmap);
-               }
-
                prtd->dma_req[0].dev = prtd;
                prtd->dma_req[1].dev = prtd;
 
@@ -215,9 +207,21 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct tegra_runtime_data *prtd = runtime->private_data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct tegra_pcm_dma_params * dmap;
 
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
 
+       dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+       if (dmap) {
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       setup_dma_tx_request(&prtd->dma_req[0], dmap);
+                       setup_dma_tx_request(&prtd->dma_req[1], dmap);
+               } else {
+                       setup_dma_rx_request(&prtd->dma_req[0], dmap);
+                       setup_dma_rx_request(&prtd->dma_req[1], dmap);
+               }
+       }
        prtd->dma_req[0].size = params_period_bytes(params);
        prtd->dma_req[1].size = prtd->dma_req[0].size;