diff options
Diffstat (limited to 'sound/soc/amd')
-rw-r--r-- | sound/soc/amd/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/amd/acp-da7219-max98357a.c | 109 | ||||
-rw-r--r-- | sound/soc/amd/acp-pcm-dma.c | 214 | ||||
-rw-r--r-- | sound/soc/amd/acp.h | 13 |
4 files changed, 261 insertions, 76 deletions
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 6cbf9cf4d1a4..58c1dcb4d255 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -8,6 +8,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH select SND_SOC_DA7219 select SND_SOC_MAX98357A select SND_SOC_ADAU7002 + select REGULATOR depends on SND_SOC_AMD_ACP && I2C help This option enables machine driver for DA7219 and MAX9835. diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index ccddc6650b9c..8e3275a96a82 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -32,6 +32,8 @@ #include <linux/clk.h> #include <linux/gpio.h> #include <linux/module.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/driver.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/acpi.h> @@ -148,7 +150,8 @@ 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_BT_INSTANCE; + machine->i2s_instance = I2S_SP_INSTANCE; + machine->capture_channel = CAP_CHANNEL1; return da7219_clk_enable(substream); } @@ -163,7 +166,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream) struct snd_soc_card *card = rtd->card; struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); - machine->i2s_instance = I2S_SP_INSTANCE; + machine->i2s_instance = I2S_BT_INSTANCE; return da7219_clk_enable(substream); } @@ -172,13 +175,24 @@ static void cz_max_shutdown(struct snd_pcm_substream *substream) da7219_clk_disable(); } -static int cz_dmic_startup(struct snd_pcm_substream *substream) +static int cz_dmic0_startup(struct snd_pcm_substream *substream) +{ + 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); + + machine->i2s_instance = I2S_BT_INSTANCE; + return da7219_clk_enable(substream); +} + +static int cz_dmic1_startup(struct snd_pcm_substream *substream) { 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); machine->i2s_instance = I2S_SP_INSTANCE; + machine->capture_channel = CAP_CHANNEL0; return da7219_clk_enable(substream); } @@ -197,23 +211,39 @@ static const struct snd_soc_ops cz_max_play_ops = { .shutdown = cz_max_shutdown, }; -static const struct snd_soc_ops cz_dmic_cap_ops = { - .startup = cz_dmic_startup, +static const struct snd_soc_ops cz_dmic0_cap_ops = { + .startup = cz_dmic0_startup, + .shutdown = cz_dmic_shutdown, +}; + +static const struct snd_soc_ops cz_dmic1_cap_ops = { + .startup = cz_dmic1_startup, .shutdown = cz_dmic_shutdown, }; static struct snd_soc_dai_link cz_dai_7219_98357[] = { { - .name = "amd-da7219-play-cap", - .stream_name = "Playback and Capture", + .name = "amd-da7219-play", + .stream_name = "Playback", .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.3.auto", + .cpu_dai_name = "designware-i2s.1.auto", .codec_dai_name = "da7219-hifi", .codec_name = "i2c-DLGS7219:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .init = cz_da7219_init, .dpcm_playback = 1, + .ops = &cz_da7219_cap_ops, + }, + { + .name = "amd-da7219-cap", + .stream_name = "Capture", + .platform_name = "acp_audio_dma.0.auto", + .cpu_dai_name = "designware-i2s.2.auto", + .codec_dai_name = "da7219-hifi", + .codec_name = "i2c-DLGS7219:00", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, .dpcm_capture = 1, .ops = &cz_da7219_cap_ops, }, @@ -221,7 +251,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .name = "amd-max98357-play", .stream_name = "HiFi Playback", .platform_name = "acp_audio_dma.0.auto", - .cpu_dai_name = "designware-i2s.1.auto", + .cpu_dai_name = "designware-i2s.3.auto", .codec_dai_name = "HiFi", .codec_name = "MX98357A:00", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF @@ -230,8 +260,22 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .ops = &cz_max_play_ops, }, { - .name = "dmic", - .stream_name = "DMIC Capture", + /* C panel DMIC */ + .name = "dmic0", + .stream_name = "DMIC0 Capture", + .platform_name = "acp_audio_dma.0.auto", + .cpu_dai_name = "designware-i2s.3.auto", + .codec_dai_name = "adau7002-hifi", + .codec_name = "ADAU7002:00", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_capture = 1, + .ops = &cz_dmic0_cap_ops, + }, + { + /* A/B panel DMIC */ + .name = "dmic1", + .stream_name = "DMIC1 Capture", .platform_name = "acp_audio_dma.0.auto", .cpu_dai_name = "designware-i2s.2.auto", .codec_dai_name = "adau7002-hifi", @@ -239,7 +283,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM, .dpcm_capture = 1, - .ops = &cz_dmic_cap_ops, + .ops = &cz_dmic1_cap_ops, }, }; @@ -278,11 +322,52 @@ static struct snd_soc_card cz_card = { .num_controls = ARRAY_SIZE(cz_mc_controls), }; +static struct regulator_consumer_supply acp_da7219_supplies[] = { + REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"), + REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"), + REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"), + REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"), +}; + +static struct regulator_init_data acp_da7219_data = { + .constraints = { + .always_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies), + .consumer_supplies = acp_da7219_supplies, +}; + +static struct regulator_config acp_da7219_cfg = { + .init_data = &acp_da7219_data, +}; + +static struct regulator_ops acp_da7219_ops = { +}; + +static struct regulator_desc acp_da7219_desc = { + .name = "reg-fixed-1.8V", + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .ops = &acp_da7219_ops, + .fixed_uV = 1800000, /* 1.8V */ + .n_voltages = 1, +}; + static int cz_probe(struct platform_device *pdev) { int ret; struct snd_soc_card *card; struct acp_platform_info *machine; + struct regulator_dev *rdev; + + acp_da7219_cfg.dev = &pdev->dev; + rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc, + &acp_da7219_cfg); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "Failed to register regulator: %d\n", + (int)PTR_ERR(rdev)); + return -EINVAL; + } machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info), GFP_KERNEL); diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index 77203841c535..e359938e3d7e 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -224,13 +224,11 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio, switch (asic_type) { case CHIP_STONEY: dmadscr[i].xfer_val |= - BIT(22) | (ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC << 16) | (size / 2); break; default: dmadscr[i].xfer_val |= - BIT(22) | (ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION << 16) | (size / 2); } @@ -322,22 +320,87 @@ static void config_acp_dma(void __iomem *acp_mmio, struct audio_substream_data *rtd, u32 asic_type) { + u16 ch_acp_sysmem, ch_acp_i2s; + acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages, rtd->pte_offset); + + if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) { + ch_acp_sysmem = rtd->ch1; + ch_acp_i2s = rtd->ch2; + } else { + ch_acp_i2s = rtd->ch1; + ch_acp_sysmem = rtd->ch2; + } /* Configure System memory <-> ACP SRAM DMA descriptors */ set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size, rtd->direction, rtd->pte_offset, - rtd->ch1, rtd->sram_bank, + ch_acp_sysmem, rtd->sram_bank, rtd->dma_dscr_idx_1, asic_type); /* Configure ACP SRAM <-> I2S DMA descriptors */ set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size, rtd->direction, rtd->sram_bank, - rtd->destination, rtd->ch2, + rtd->destination, ch_acp_i2s, rtd->dma_dscr_idx_2, asic_type); } +static void acp_dma_cap_channel_enable(void __iomem *acp_mmio, + u16 cap_channel) +{ + u32 val, ch_reg, imr_reg, res_reg; + + switch (cap_channel) { + case CAP_CHANNEL1: + ch_reg = mmACP_I2SMICSP_RER1; + res_reg = mmACP_I2SMICSP_RCR1; + imr_reg = mmACP_I2SMICSP_IMR1; + break; + case CAP_CHANNEL0: + default: + ch_reg = mmACP_I2SMICSP_RER0; + res_reg = mmACP_I2SMICSP_RCR0; + imr_reg = mmACP_I2SMICSP_IMR0; + break; + } + val = acp_reg_read(acp_mmio, + mmACP_I2S_16BIT_RESOLUTION_EN); + if (val & ACP_I2S_MIC_16BIT_RESOLUTION_EN) { + acp_reg_write(0x0, acp_mmio, ch_reg); + /* Set 16bit resolution on capture */ + acp_reg_write(0x2, acp_mmio, res_reg); + } + val = acp_reg_read(acp_mmio, imr_reg); + val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK; + val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK; + acp_reg_write(val, acp_mmio, imr_reg); + acp_reg_write(0x1, acp_mmio, ch_reg); +} + +static void acp_dma_cap_channel_disable(void __iomem *acp_mmio, + u16 cap_channel) +{ + u32 val, ch_reg, imr_reg; + + switch (cap_channel) { + case CAP_CHANNEL1: + imr_reg = mmACP_I2SMICSP_IMR1; + ch_reg = mmACP_I2SMICSP_RER1; + break; + case CAP_CHANNEL0: + default: + imr_reg = mmACP_I2SMICSP_IMR0; + ch_reg = mmACP_I2SMICSP_RER0; + break; + } + val = acp_reg_read(acp_mmio, imr_reg); + val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK; + val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK; + acp_reg_write(val, acp_mmio, imr_reg); + acp_reg_write(0x0, acp_mmio, ch_reg); +} + /* Start a given DMA channel transfer */ -static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num) +static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular) { u32 dma_ctrl; @@ -356,10 +419,8 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num) switch (ch_num) { case ACP_TO_I2S_DMA_CH_NUM: - case ACP_TO_SYSRAM_CH_NUM: case I2S_TO_ACP_DMA_CH_NUM: case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM: - case ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM: case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM: dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK; break; @@ -368,8 +429,11 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num) break; } - /* circular for both DMA channel */ - dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK; + /* enable for ACP to SRAM DMA channel */ + if (is_circular == true) + dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK; + else + dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK; acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num); } @@ -613,6 +677,7 @@ static int acp_deinit(void __iomem *acp_mmio) /* ACP DMA irq handler routine for playback, capture usecases */ static irqreturn_t dma_irq_handler(int irq, void *arg) { + u16 dscr_idx; u32 intr_flag, ext_intr_status; struct audio_drv_data *irq_data; void __iomem *acp_mmio; @@ -644,32 +709,39 @@ static irqreturn_t dma_irq_handler(int irq, void *arg) if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) { valid_irq = true; + if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_14) == + CAPTURE_START_DMA_DESCR_CH15) + dscr_idx = CAPTURE_END_DMA_DESCR_CH14; + else + dscr_idx = CAPTURE_START_DMA_DESCR_CH14; + config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx, + 1, 0); + acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false); + snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream); acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16, acp_mmio, mmACP_EXTERNAL_INTR_STAT); } - if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) { - valid_irq = true; - acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16, - acp_mmio, mmACP_EXTERNAL_INTR_STAT); - } - if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) { valid_irq = true; + if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_10) == + CAPTURE_START_DMA_DESCR_CH11) + dscr_idx = CAPTURE_END_DMA_DESCR_CH10; + else + dscr_idx = CAPTURE_START_DMA_DESCR_CH10; + config_acp_dma_channel(acp_mmio, + ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM, + dscr_idx, 1, 0); + acp_dma_start(acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM, + false); + snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream); acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16, acp_mmio, mmACP_EXTERNAL_INTR_STAT); } - if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) { - valid_irq = true; - acp_reg_write((intr_flag & - BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16, - acp_mmio, mmACP_EXTERNAL_INTR_STAT); - } - if (valid_irq) return IRQ_HANDLED; else @@ -773,7 +845,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream, if (WARN_ON(!rtd)) return -EINVAL; - rtd->i2s_instance = pinfo->i2s_instance; + if (pinfo) { + rtd->i2s_instance = pinfo->i2s_instance; + rtd->capture_channel = pinfo->capture_channel; + } if (adata->asic_type == CHIP_STONEY) { val = acp_reg_read(adata->acp_mmio, mmACP_I2S_16BIT_RESOLUTION_EN); @@ -841,8 +916,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream, switch (rtd->i2s_instance) { case I2S_BT_INSTANCE: rtd->pte_offset = ACP_ST_BT_CAPTURE_PTE_OFFSET; - rtd->ch1 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM; - rtd->ch2 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM; + rtd->ch1 = I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM; + rtd->ch2 = ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM; rtd->sram_bank = ACP_SRAM_BANK_4_ADDRESS; rtd->destination = FROM_BLUETOOTH; rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10; @@ -851,13 +926,14 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream, mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH; rtd->byte_cnt_low_reg_offset = mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW; + rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11; adata->capture_i2sbt_stream = substream; break; case I2S_SP_INSTANCE: default: rtd->pte_offset = ACP_CAPTURE_PTE_OFFSET; - rtd->ch1 = ACP_TO_SYSRAM_CH_NUM; - rtd->ch2 = I2S_TO_ACP_DMA_CH_NUM; + rtd->ch1 = I2S_TO_ACP_DMA_CH_NUM; + rtd->ch2 = ACP_TO_SYSRAM_CH_NUM; switch (adata->asic_type) { case CHIP_STONEY: rtd->pte_offset = ACP_ST_CAPTURE_PTE_OFFSET; @@ -874,6 +950,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream, mmACP_I2S_RECEIVED_BYTE_CNT_HIGH; rtd->byte_cnt_low_reg_offset = mmACP_I2S_RECEIVED_BYTE_CNT_LOW; + rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15; adata->capture_i2ssp_stream = substream; } } @@ -927,6 +1004,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream) u32 buffersize; u32 pos = 0; u64 bytescount = 0; + u16 dscr; + u32 period_bytes, delay; struct snd_pcm_runtime *runtime = substream->runtime; struct audio_substream_data *rtd = runtime->private_data; @@ -934,12 +1013,25 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream) if (!rtd) return -EINVAL; - buffersize = frames_to_bytes(runtime, runtime->buffer_size); - bytescount = acp_get_byte_count(rtd); - - if (bytescount > rtd->bytescount) - bytescount -= rtd->bytescount; - pos = do_div(bytescount, buffersize); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + period_bytes = frames_to_bytes(runtime, runtime->period_size); + dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr); + if (dscr == rtd->dma_dscr_idx_1) + pos = period_bytes; + else + pos = 0; + bytescount = acp_get_byte_count(rtd); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + delay = do_div(bytescount, period_bytes); + runtime->delay = bytes_to_frames(runtime, delay); + } else { + buffersize = frames_to_bytes(runtime, runtime->buffer_size); + bytescount = acp_get_byte_count(rtd); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + } return bytes_to_frames(runtime, pos); } @@ -953,16 +1045,24 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct audio_substream_data *rtd = runtime->private_data; + u16 ch_acp_sysmem, ch_acp_i2s; if (!rtd) return -EINVAL; + if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) { + ch_acp_sysmem = rtd->ch1; + ch_acp_i2s = rtd->ch2; + } else { + ch_acp_i2s = rtd->ch1; + ch_acp_sysmem = rtd->ch2; + } config_acp_dma_channel(rtd->acp_mmio, - rtd->ch1, + ch_acp_sysmem, rtd->dma_dscr_idx_1, NUM_DSCRS_PER_CHANNEL, 0); config_acp_dma_channel(rtd->acp_mmio, - rtd->ch2, + ch_acp_i2s, rtd->dma_dscr_idx_2, NUM_DSCRS_PER_CHANNEL, 0); return 0; @@ -971,7 +1071,6 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream) static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd) { int ret; - u64 bytescount = 0; struct snd_pcm_runtime *runtime = substream->runtime; struct audio_substream_data *rtd = runtime->private_data; @@ -982,37 +1081,32 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: - bytescount = acp_get_byte_count(rtd); - if (rtd->bytescount == 0) - rtd->bytescount = bytescount; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - acp_dma_start(rtd->acp_mmio, rtd->ch1); - acp_dma_start(rtd->acp_mmio, rtd->ch2); + rtd->bytescount = acp_get_byte_count(rtd); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (rtd->capture_channel == CAP_CHANNEL0) { + acp_dma_cap_channel_disable(rtd->acp_mmio, + CAP_CHANNEL1); + acp_dma_cap_channel_enable(rtd->acp_mmio, + CAP_CHANNEL0); + } + if (rtd->capture_channel == CAP_CHANNEL1) { + acp_dma_cap_channel_disable(rtd->acp_mmio, + CAP_CHANNEL0); + acp_dma_cap_channel_enable(rtd->acp_mmio, + CAP_CHANNEL1); + } + acp_dma_start(rtd->acp_mmio, rtd->ch1, true); } else { - acp_dma_start(rtd->acp_mmio, rtd->ch2); - acp_dma_start(rtd->acp_mmio, rtd->ch1); + acp_dma_start(rtd->acp_mmio, rtd->ch1, true); + acp_dma_start(rtd->acp_mmio, rtd->ch2, true); } ret = 0; break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: - /* For playback, non circular dma should be stopped first - * i.e Sysram to acp dma transfer channel(rtd->ch1) should be - * stopped before stopping cirular dma which is acp sram to i2s - * fifo dma transfer channel(rtd->ch2). Where as in Capture - * scenario, i2s fifo to acp sram dma channel(rtd->ch2) stopped - * first before stopping acp sram to sysram which is circular - * dma(rtd->ch1). - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - acp_dma_stop(rtd->acp_mmio, rtd->ch1); - ret = acp_dma_stop(rtd->acp_mmio, rtd->ch2); - } else { - acp_dma_stop(rtd->acp_mmio, rtd->ch2); - ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1); - } - rtd->bytescount = 0; + acp_dma_stop(rtd->acp_mmio, rtd->ch2); + ret = acp_dma_stop(rtd->acp_mmio, rtd->ch1); break; default: ret = -EINVAL; diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h index 9cd3e96c84d4..be3963e8f4fa 100644 --- a/sound/soc/amd/acp.h +++ b/sound/soc/amd/acp.h @@ -55,6 +55,8 @@ #define I2S_SP_INSTANCE 0x01 #define I2S_BT_INSTANCE 0x02 +#define CAP_CHANNEL0 0x00 +#define CAP_CHANNEL1 0x01 #define ACP_TILE_ON_MASK 0x03 #define ACP_TILE_OFF_MASK 0x02 @@ -72,16 +74,16 @@ #define ACP_TO_I2S_DMA_CH_NUM 13 /* Capture DMA channels */ -#define ACP_TO_SYSRAM_CH_NUM 14 -#define I2S_TO_ACP_DMA_CH_NUM 15 +#define I2S_TO_ACP_DMA_CH_NUM 14 +#define ACP_TO_SYSRAM_CH_NUM 15 /* Playback DMA Channels for I2S BT instance */ #define SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM 8 #define ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM 9 /* Capture DMA Channels for I2S BT Instance */ -#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 10 -#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 11 +#define I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM 10 +#define ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM 11 #define NUM_DSCRS_PER_CHANNEL 2 @@ -125,6 +127,7 @@ struct audio_substream_data { unsigned int order; u16 num_of_pages; u16 i2s_instance; + u16 capture_channel; u16 direction; u16 ch1; u16 ch2; @@ -135,6 +138,7 @@ struct audio_substream_data { u32 sram_bank; u32 byte_cnt_high_reg_offset; u32 byte_cnt_low_reg_offset; + u32 dma_curr_dscr; uint64_t size; u64 bytescount; void __iomem *acp_mmio; @@ -155,6 +159,7 @@ struct audio_drv_data { */ struct acp_platform_info { u16 i2s_instance; + u16 capture_channel; }; union acp_dma_count { |