]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
ASoC: AMD: Fix simultaneous playback and capture on different channel
authorAkshu Agrawal <akshu.agrawal@amd.com>
Mon, 10 Sep 2018 17:20:27 +0000 (22:50 +0530)
committerMark Brown <broonie@kernel.org>
Mon, 10 Sep 2018 17:46:09 +0000 (18:46 +0100)
If capture and playback are started on different channel (I2S/BT)
there is a possibilty that channel information passed from machine driver
is overwritten before the configuration is done in dma driver.
Example:
113.597588: cz_max_startup: ---playback sets BT channel
113.597694: cz_dmic1_startup: ---capture sets I2S channel
113.597979: acp_dma_hw_params: ---configures capture for I2S channel
113.598114: acp_dma_hw_params: ---configures playback for I2S channel

This is fixed by having 2 separate instance for playback and capture.

Signed-off-by: Akshu Agrawal <akshu.agrawal@amd.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/amd/acp-da7219-max98357a.c
sound/soc/amd/acp-pcm-dma.c
sound/soc/amd/acp.h

index 3879cccbd2c002dedddbb3d70551408165fb5886..717a017f0db6f7764f9f4cdef97cb461ae44708d 100644 (file)
@@ -133,7 +133,7 @@ static const struct snd_pcm_hw_constraint_list constraints_channels = {
        .mask = 0,
 };
 
-static int cz_da7219_startup(struct snd_pcm_substream *substream)
+static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -150,7 +150,28 @@ static int cz_da7219_startup(struct snd_pcm_substream *substream)
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                   &constraints_rates);
 
-       machine->i2s_instance = I2S_SP_INSTANCE;
+       machine->play_i2s_instance = I2S_SP_INSTANCE;
+       return da7219_clk_enable(substream);
+}
+
+static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_card *card = rtd->card;
+       struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+       /*
+        * On this platform for PCM device we support stereo
+        */
+
+       runtime->hw.channels_max = DUAL_CHANNEL;
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                                  &constraints_channels);
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+                                  &constraints_rates);
+
+       machine->cap_i2s_instance = I2S_SP_INSTANCE;
        machine->capture_channel = CAP_CHANNEL1;
        return da7219_clk_enable(substream);
 }
@@ -177,7 +198,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream)
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                   &constraints_rates);
 
-       machine->i2s_instance = I2S_BT_INSTANCE;
+       machine->play_i2s_instance = I2S_BT_INSTANCE;
        return da7219_clk_enable(substream);
 }
 
@@ -203,7 +224,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream)
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                   &constraints_rates);
 
-       machine->i2s_instance = I2S_BT_INSTANCE;
+       machine->cap_i2s_instance = I2S_BT_INSTANCE;
        return da7219_clk_enable(substream);
 }
 
@@ -224,7 +245,7 @@ static int cz_dmic1_startup(struct snd_pcm_substream *substream)
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                   &constraints_rates);
 
-       machine->i2s_instance = I2S_SP_INSTANCE;
+       machine->cap_i2s_instance = I2S_SP_INSTANCE;
        machine->capture_channel = CAP_CHANNEL0;
        return da7219_clk_enable(substream);
 }
@@ -234,8 +255,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
        da7219_clk_disable();
 }
 
+static const struct snd_soc_ops cz_da7219_play_ops = {
+       .startup = cz_da7219_play_startup,
+       .shutdown = cz_da7219_shutdown,
+};
+
 static const struct snd_soc_ops cz_da7219_cap_ops = {
-       .startup = cz_da7219_startup,
+       .startup = cz_da7219_cap_startup,
        .shutdown = cz_da7219_shutdown,
 };
 
@@ -266,7 +292,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                                | SND_SOC_DAIFMT_CBM_CFM,
                .init = cz_da7219_init,
                .dpcm_playback = 1,
-               .ops = &cz_da7219_cap_ops,
+               .ops = &cz_da7219_play_ops,
        },
        {
                .name = "amd-da7219-cap",
index e359938e3d7e16bfd3995084be4e1b20d6b1989e..8f3bc6e37f265e2a65b3d30db87a8877f21e455e 100644 (file)
@@ -846,8 +846,12 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
 
        if (pinfo) {
-               rtd->i2s_instance = pinfo->i2s_instance;
-               rtd->capture_channel = pinfo->capture_channel;
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       rtd->i2s_instance = pinfo->play_i2s_instance;
+               } else {
+                       rtd->i2s_instance = pinfo->cap_i2s_instance;
+                       rtd->capture_channel = pinfo->capture_channel;
+               }
        }
        if (adata->asic_type == CHIP_STONEY) {
                val = acp_reg_read(adata->acp_mmio,
index be3963e8f4fac527c2f048f595575c5b88397517..dbbb1a85638db68c61f758c63fe5aa2cbbfcc2ca 100644 (file)
@@ -158,7 +158,8 @@ struct audio_drv_data {
  * and dma driver
  */
 struct acp_platform_info {
-       u16 i2s_instance;
+       u16 play_i2s_instance;
+       u16 cap_i2s_instance;
        u16 capture_channel;
 };