diff options
Diffstat (limited to 'sound/soc/amd')
33 files changed, 1208 insertions, 210 deletions
diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c index 42c2322cd11b..365209ea53f3 100644 --- a/sound/soc/amd/acp-config.c +++ b/sound/soc/amd/acp-config.c @@ -321,5 +321,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[] = { }; EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_machines); +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_machines[] = { + { + .id = "AMDI1010", + .drv_name = "acp70-dsp", + .pdata = &acp_quirk_data, + .fw_filename = "sof-acp_7_0.ri", + .sof_tplg_filename = "sof-acp_7_0.tplg", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp70_sof_machines); + MODULE_DESCRIPTION("AMD ACP Machine Configuration Module"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/amd/acp-es8336.c b/sound/soc/amd/acp-es8336.c index e079b3218c6f..3756b8bef17b 100644 --- a/sound/soc/amd/acp-es8336.c +++ b/sound/soc/amd/acp-es8336.c @@ -203,8 +203,10 @@ static int st_es8336_late_probe(struct snd_soc_card *card) codec_dev = acpi_get_first_physical_node(adev); acpi_dev_put(adev); - if (!codec_dev) + if (!codec_dev) { dev_err(card->dev, "can not find codec dev\n"); + return -ENODEV; + } ret = devm_acpi_dev_add_driver_gpios(codec_dev, acpi_es8336_gpios); if (ret) diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index b857e2676fe8..897dde630022 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -1426,7 +1426,7 @@ static const struct dev_pm_ops acp_pm_ops = { static struct platform_driver acp_dma_driver = { .probe = acp_audio_probe, - .remove_new = acp_audio_remove, + .remove = acp_audio_remove, .driver = { .name = DRV_NAME, .pm = &acp_pm_ops, diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 30590a23ad63..88391e4c17e3 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -13,6 +13,10 @@ config SND_SOC_AMD_ACP_COMMON This option enables common modules for Audio-Coprocessor i.e. ACP IP block on AMD platforms. +config SND_SOC_ACPI_AMD_MATCH + tristate + select SND_SOC_ACPI if ACPI + if SND_SOC_AMD_ACP_COMMON config SND_SOC_AMD_ACP_PDM @@ -115,6 +119,24 @@ config SND_SOC_AMD_SOF_MACH help This option enables SOF sound card support for ACP audio. +config SND_SOC_AMD_SOF_SDW_MACH + tristate "AMD SOF Soundwire Machine Driver Support" + depends on X86 && PCI && ACPI + depends on SOUNDWIRE + select SND_SOC_SDW_UTILS + select SND_SOC_DMIC + select SND_SOC_RT711_SDW + select SND_SOC_RT711_SDCA_SDW + select SND_SOC_RT1316_SDW + select SND_SOC_RT715_SDW + select SND_SOC_RT715_SDCA_SDW + help + This option enables SOF sound card support for SoundWire enabled + AMD platforms along with ACP PDM controller. + Say Y if you want to enable SoundWire based machine driver support + on AMD platform. + If unsure select "N". + endif # SND_SOC_AMD_ACP_COMMON config SND_AMD_SOUNDWIRE_ACPI diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index b068bf1f920e..82cf5d180b3a 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -22,6 +22,8 @@ snd-acp70-y := acp70.o snd-acp-mach-y := acp-mach-common.o snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o snd-acp-sof-mach-y := acp-sof-mach.o +snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o +snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o @@ -38,3 +40,5 @@ obj-$(CONFIG_SND_AMD_SOUNDWIRE_ACPI) += snd-amd-sdw-acpi.o obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o +obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o +obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 60cbc881be6e..56ce9e4b6acc 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -60,6 +60,8 @@ static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id) switch (chip->acp_rev) { case ACP63_DEV: + case ACP70_DEV: + case ACP71_DEV: val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, adata->lrclk_div); val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, adata->bclk_div); break; @@ -95,9 +97,11 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas { struct device *dev = dai->component->dev; struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai); + struct acp_chip_info *chip; struct acp_stream *stream; int slot_len, no_of_slots; + chip = dev_get_platdata(dev); switch (slot_width) { case SLOT_WIDTH_8: slot_len = 8; @@ -116,15 +120,38 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas return -EINVAL; } - switch (slots) { - case 1 ... 7: - no_of_slots = slots; + switch (chip->acp_rev) { + case ACP3X_DEV: + case ACP6X_DEV: + switch (slots) { + case 1 ... 7: + no_of_slots = slots; + break; + case 8: + no_of_slots = 0; + break; + default: + dev_err(dev, "Unsupported slots %d\n", slots); + return -EINVAL; + } break; - case 8: - no_of_slots = 0; + case ACP63_DEV: + case ACP70_DEV: + case ACP71_DEV: + switch (slots) { + case 1 ... 31: + no_of_slots = slots; + break; + case 32: + no_of_slots = 0; + break; + default: + dev_err(dev, "Unsupported slots %d\n", slots); + return -EINVAL; + } break; default: - dev_err(dev, "Unsupported slots %d\n", slots); + dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev); return -EINVAL; } @@ -132,12 +159,30 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas spin_lock_irq(&adata->acp_lock); list_for_each_entry(stream, &adata->stream_list, list) { - if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) - adata->tdm_tx_fmt[stream->dai_id - 1] = + switch (chip->acp_rev) { + case ACP3X_DEV: + case ACP6X_DEV: + if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + adata->tdm_tx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 15) | (slot_len << 18); - else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) - adata->tdm_rx_fmt[stream->dai_id - 1] = + else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) + adata->tdm_rx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 15) | (slot_len << 18); + break; + case ACP63_DEV: + case ACP70_DEV: + case ACP71_DEV: + if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + adata->tdm_tx_fmt[stream->dai_id - 1] = + FRM_LEN | (slots << 13) | (slot_len << 18); + else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) + adata->tdm_rx_fmt[stream->dai_id - 1] = + FRM_LEN | (slots << 13) | (slot_len << 18); + break; + default: + dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev); + return -EINVAL; + } } spin_unlock_irq(&adata->acp_lock); return 0; @@ -296,6 +341,41 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_ default: return -EINVAL; } + + switch (params_rate(params)) { + case 8000: + case 16000: + case 24000: + case 48000: + case 96000: + case 192000: + switch (params_channels(params)) { + case 2: + break; + case 4: + bclk_div_val = bclk_div_val >> 1; + lrclk_div_val = lrclk_div_val << 1; + break; + case 8: + bclk_div_val = bclk_div_val >> 2; + lrclk_div_val = lrclk_div_val << 2; + break; + case 16: + bclk_div_val = bclk_div_val >> 3; + lrclk_div_val = lrclk_div_val << 3; + break; + case 32: + bclk_div_val = bclk_div_val >> 4; + lrclk_div_val = lrclk_div_val << 4; + break; + default: + dev_err(dev, "Unsupported channels %#x\n", + params_channels(params)); + } + break; + default: + break; + } adata->lrclk_div = lrclk_div_val; adata->bclk_div = bclk_div_val; } @@ -321,16 +401,16 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { switch (dai->driver->id) { case I2S_BT_INSTANCE: - water_val = ACP_BT_TX_INTR_WATERMARK_SIZE; + water_val = ACP_BT_TX_INTR_WATERMARK_SIZE(adata); reg_val = ACP_BTTDM_ITER; ier_val = ACP_BTTDM_IER; - buf_reg = ACP_BT_TX_RINGBUFSIZE; + buf_reg = ACP_BT_TX_RINGBUFSIZE(adata); break; case I2S_SP_INSTANCE: - water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE; + water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE(adata); reg_val = ACP_I2STDM_ITER; ier_val = ACP_I2STDM_IER; - buf_reg = ACP_I2S_TX_RINGBUFSIZE; + buf_reg = ACP_I2S_TX_RINGBUFSIZE(adata); break; case I2S_HS_INSTANCE: water_val = ACP_HS_TX_INTR_WATERMARK_SIZE; @@ -345,16 +425,16 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct } else { switch (dai->driver->id) { case I2S_BT_INSTANCE: - water_val = ACP_BT_RX_INTR_WATERMARK_SIZE; + water_val = ACP_BT_RX_INTR_WATERMARK_SIZE(adata); reg_val = ACP_BTTDM_IRER; ier_val = ACP_BTTDM_IER; - buf_reg = ACP_BT_RX_RINGBUFSIZE; + buf_reg = ACP_BT_RX_RINGBUFSIZE(adata); break; case I2S_SP_INSTANCE: - water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE; + water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE(adata); reg_val = ACP_I2STDM_IRER; ier_val = ACP_I2STDM_IER; - buf_reg = ACP_I2S_RX_RINGBUFSIZE; + buf_reg = ACP_I2S_RX_RINGBUFSIZE(adata); break; case I2S_HS_INSTANCE: water_val = ACP_HS_RX_INTR_WATERMARK_SIZE; @@ -367,14 +447,15 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct return -EINVAL; } } + writel(period_bytes, adata->acp_base + water_val); writel(buf_size, adata->acp_base + buf_reg); + if (rsrc->soc_mclk) + acp_set_i2s_clk(adata, dai->driver->id); val = readl(adata->acp_base + reg_val); val = val | BIT(0); writel(val, adata->acp_base + reg_val); writel(1, adata->acp_base + ier_val); - if (rsrc->soc_mclk) - acp_set_i2s_clk(adata, dai->driver->id); return 0; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -436,52 +517,67 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d { struct device *dev = dai->component->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip; struct acp_resource *rsrc = adata->rsrc; struct acp_stream *stream = substream->runtime->private_data; u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0; u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl; unsigned int dir = substream->stream; + chip = dev_get_platdata(dev); switch (dai->driver->id) { case I2S_SP_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_I2S_TX_DMA_SIZE; + reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata); acp_fifo_addr = rsrc->sram_pte_offset + SP_PB_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_I2S_TX_FIFOADDR; - reg_fifo_size = ACP_I2S_TX_FIFOSIZE; - - phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR); + reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata); + reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata); + + if (chip->acp_rev >= ACP70_DEV) + phy_addr = ACP7x_I2S_SP_TX_MEM_WINDOW_START; + else + phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; + writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata)); } else { - reg_dma_size = ACP_I2S_RX_DMA_SIZE; + reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata); acp_fifo_addr = rsrc->sram_pte_offset + SP_CAPT_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_I2S_RX_FIFOADDR; - reg_fifo_size = ACP_I2S_RX_FIFOSIZE; - phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR); + reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata); + reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata); + + if (chip->acp_rev >= ACP70_DEV) + phy_addr = ACP7x_I2S_SP_RX_MEM_WINDOW_START; + else + phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; + writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata)); } break; case I2S_BT_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_BT_TX_DMA_SIZE; + reg_dma_size = ACP_BT_TX_DMA_SIZE(adata); acp_fifo_addr = rsrc->sram_pte_offset + BT_PB_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_BT_TX_FIFOADDR; - reg_fifo_size = ACP_BT_TX_FIFOSIZE; - - phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR); + reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata); + reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata); + + if (chip->acp_rev >= ACP70_DEV) + phy_addr = ACP7x_I2S_BT_TX_MEM_WINDOW_START; + else + phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; + writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata)); } else { - reg_dma_size = ACP_BT_RX_DMA_SIZE; + reg_dma_size = ACP_BT_RX_DMA_SIZE(adata); acp_fifo_addr = rsrc->sram_pte_offset + BT_CAPT_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_BT_RX_FIFOADDR; - reg_fifo_size = ACP_BT_RX_FIFOSIZE; - - phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR); + reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata); + reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata); + + if (chip->acp_rev >= ACP70_DEV) + phy_addr = ACP7x_I2S_BT_RX_MEM_WINDOW_START; + else + phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; + writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata)); } break; case I2S_HS_INSTANCE: @@ -492,7 +588,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_HS_TX_FIFOADDR; reg_fifo_size = ACP_HS_TX_FIFOSIZE; - phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset; + if (chip->acp_rev >= ACP70_DEV) + phy_addr = ACP7x_I2S_HS_TX_MEM_WINDOW_START; + else + phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset; writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR); } else { reg_dma_size = ACP_HS_RX_DMA_SIZE; @@ -501,7 +600,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_HS_RX_FIFOADDR; reg_fifo_size = ACP_HS_RX_FIFOSIZE; - phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset; + if (chip->acp_rev >= ACP70_DEV) + phy_addr = ACP7x_I2S_HS_RX_MEM_WINDOW_START; + else + phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset; writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR); } break; @@ -584,29 +686,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d return 0; } -static int acp_i2s_probe(struct snd_soc_dai *dai) -{ - struct device *dev = dai->component->dev; - struct acp_dev_data *adata = dev_get_drvdata(dev); - struct acp_resource *rsrc = adata->rsrc; - unsigned int val; - - if (!adata->acp_base) { - dev_err(dev, "I2S base is NULL\n"); - return -EINVAL; - } - - val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset); - if (val != rsrc->i2s_mode) { - dev_err(dev, "I2S Mode not supported val %x\n", val); - return -EINVAL; - } - - return 0; -} - const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = { - .probe = acp_i2s_probe, .startup = acp_i2s_startup, .hw_params = acp_i2s_hwparams, .prepare = acp_i2s_prepare, @@ -616,5 +696,6 @@ const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = { }; EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON); +MODULE_DESCRIPTION("AMD ACP Audio I2S controller"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_ALIAS(DRV_NAME); diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 3be7c6d55a6f..be01b178172e 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -113,40 +113,40 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, switch (dai->driver->id) { case I2S_SP_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_I2S_TX_DMA_SIZE; + reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata); acp_fifo_addr = rsrc->sram_pte_offset + SP_PB_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_I2S_TX_FIFOADDR; - reg_fifo_size = ACP_I2S_TX_FIFOSIZE; + reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata); + reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata); phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata)); } else { - reg_dma_size = ACP_I2S_RX_DMA_SIZE; + reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata); acp_fifo_addr = rsrc->sram_pte_offset + SP_CAPT_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_I2S_RX_FIFOADDR; - reg_fifo_size = ACP_I2S_RX_FIFOSIZE; + reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata); + reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata); phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata)); } break; case I2S_BT_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_BT_TX_DMA_SIZE; + reg_dma_size = ACP_BT_TX_DMA_SIZE(adata); acp_fifo_addr = rsrc->sram_pte_offset + BT_PB_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_BT_TX_FIFOADDR; - reg_fifo_size = ACP_BT_TX_FIFOSIZE; + reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata); + reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata); phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata)); } else { - reg_dma_size = ACP_BT_RX_DMA_SIZE; + reg_dma_size = ACP_BT_RX_DMA_SIZE(adata); acp_fifo_addr = rsrc->sram_pte_offset + BT_CAPT_FIFO_ADDR_OFFSET; - reg_fifo_addr = ACP_BT_RX_FIFOADDR; - reg_fifo_size = ACP_BT_RX_FIFOSIZE; + reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata); + reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata); phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata)); } break; case I2S_HS_INSTANCE: @@ -270,6 +270,7 @@ static int acp_power_on(struct acp_chip_info *chip) acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL; break; case ACP70_DEV: + case ACP71_DEV: acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS; acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL; break; @@ -321,6 +322,8 @@ int acp_init(struct acp_chip_info *chip) pr_err("ACP reset failed\n"); return ret; } + if (chip->acp_rev >= ACP70_DEV) + writel(0, chip->base + ACP_ZSC_DSP_CTRL); return 0; } EXPORT_SYMBOL_NS_GPL(acp_init, SND_SOC_ACP_COMMON); @@ -334,8 +337,10 @@ int acp_deinit(struct acp_chip_info *chip) if (ret) return ret; - if (chip->acp_rev != ACP70_DEV) + if (chip->acp_rev < ACP70_DEV) writel(0, chip->base + ACP_CONTROL); + else + writel(0x01, chip->base + ACP_ZSC_DSP_CTRL); return 0; } EXPORT_SYMBOL_NS_GPL(acp_deinit, SND_SOC_ACP_COMMON); @@ -456,6 +461,7 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) check_acp6x_config(chip); break; case ACP70_DEV: + case ACP71_DEV: pdm_addr = ACP70_PDM_ADDR; check_acp70_config(chip); break; @@ -475,4 +481,5 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) } EXPORT_SYMBOL_NS_GPL(check_acp_config, SND_SOC_ACP_COMMON); +MODULE_DESCRIPTION("AMD ACP legacy common features"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c index 47c3b5f167f5..d104f7e8fdcd 100644 --- a/sound/soc/amd/acp/acp-legacy-mach.c +++ b/sound/soc/amd/acp/acp-legacy-mach.c @@ -227,6 +227,8 @@ static const struct platform_device_id board_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(platform, board_ids); + static struct platform_driver acp_asoc_audio = { .driver = { .pm = &snd_soc_pm_ops, @@ -240,11 +242,4 @@ module_platform_driver(acp_asoc_audio); MODULE_IMPORT_NS(SND_SOC_AMD_MACH); MODULE_DESCRIPTION("ACP chrome audio support"); -MODULE_ALIAS("platform:acp3xalc56821019"); -MODULE_ALIAS("platform:acp3xalc5682sm98360"); -MODULE_ALIAS("platform:acp3xalc5682s1019"); -MODULE_ALIAS("platform:acp3x-es83xx"); -MODULE_ALIAS("platform:rmb-nau8825-max"); -MODULE_ALIAS("platform:rmb-rt5682s-rt1019"); -MODULE_ALIAS("platform:acp-pdm-mach"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index a36300a4ed8a..e9ff4815c12c 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -1766,7 +1766,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card) } else if (drv_data->platform == ACP63) { links[i].platforms = platform_acp63_component; links[i].num_platforms = ARRAY_SIZE(platform_acp63_component); - } else if (drv_data->platform == ACP70) { + } else if ((drv_data->platform == ACP70) || (drv_data->platform == ACP71)) { links[i].platforms = platform_acp70_component; links[i].num_platforms = ARRAY_SIZE(platform_acp70_component); } else { diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h index a48546d8d407..93d9e3886b7e 100644 --- a/sound/soc/amd/acp/acp-mach.h +++ b/sound/soc/amd/acp/acp-mach.h @@ -56,6 +56,7 @@ enum platform_end_point { REMBRANDT, ACP63, ACP70, + ACP71, }; struct acp_mach_ops { diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c index ad320b29e87d..f7450a5bd103 100644 --- a/sound/soc/amd/acp/acp-pci.c +++ b/sound/soc/amd/acp/acp-pci.c @@ -95,11 +95,16 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id chip->name = "acp_asoc_acp70"; chip->acp_rev = ACP70_DEV; break; + case 0x71: + chip->name = "acp_asoc_acp70"; + chip->acp_rev = ACP71_DEV; + break; default: dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision); ret = -EINVAL; goto release_regions; } + chip->flag = flag; dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0); if (IS_ERR(dmic_dev)) { dev_err(dev, "failed to create DMIC device\n"); @@ -139,7 +144,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id } } - chip->flag = flag; memset(&pdevinfo, 0, sizeof(pdevinfo)); pdevinfo.name = chip->name; @@ -199,10 +203,12 @@ static int __maybe_unused snd_acp_resume(struct device *dev) ret = acp_init(chip); if (ret) dev_err(dev, "ACP init failed\n"); - child = chip->chip_pdev->dev; - adata = dev_get_drvdata(&child); - if (adata) - acp_enable_interrupts(adata); + if (chip->chip_pdev) { + child = chip->chip_pdev->dev; + adata = dev_get_drvdata(&child); + if (adata) + acp_enable_interrupts(adata); + } return ret; } @@ -247,6 +253,7 @@ static struct pci_driver snd_amd_acp_pci_driver = { }; module_pci_driver(snd_amd_acp_pci_driver); +MODULE_DESCRIPTION("AMD ACP common PCI support"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_ACP_COMMON); MODULE_ALIAS(DRV_NAME); diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c index f754bf79b5e3..22dd8988d005 100644 --- a/sound/soc/amd/acp/acp-pdm.c +++ b/sound/soc/amd/acp/acp-pdm.c @@ -31,9 +31,11 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream, struct acp_stream *stream = substream->runtime->private_data; struct device *dev = dai->component->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip; u32 physical_addr, size_dmic, period_bytes; unsigned int dmic_ctrl; + chip = dev_get_platdata(dev); /* Enable default DMIC clk */ writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL); dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL); @@ -45,7 +47,10 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream, size_dmic = frames_to_bytes(substream->runtime, substream->runtime->buffer_size); - physical_addr = stream->reg_offset + MEM_WINDOW_START; + if (chip->acp_rev >= ACP70_DEV) + physical_addr = ACP7x_DMIC_MEM_WINDOW_START; + else + physical_addr = stream->reg_offset + MEM_WINDOW_START; /* Init DMIC Ring buffer */ writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR); @@ -178,5 +183,6 @@ const struct snd_soc_dai_ops acp_dmic_dai_ops = { }; EXPORT_SYMBOL_NS_GPL(acp_dmic_dai_ops, SND_SOC_ACP_COMMON); +MODULE_DESCRIPTION("AMD ACP Audio PDM controller"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_ALIAS(DRV_NAME); diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index aaac8aa744cb..3a7a467b7063 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -68,6 +68,46 @@ static const struct snd_pcm_hardware acp_pcm_hardware_capture = { .periods_max = CAPTURE_MAX_NUM_PERIODS, }; +static const struct snd_pcm_hardware acp6x_pcm_hardware_playback = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 32, + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE, + .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, + .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, + .periods_min = PLAYBACK_MIN_NUM_PERIODS, + .periods_max = PLAYBACK_MAX_NUM_PERIODS, +}; + +static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 32, + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, + .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, + .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, + .periods_min = CAPTURE_MIN_NUM_PERIODS, + .periods_max = CAPTURE_MAX_NUM_PERIODS, +}; + int acp_machine_select(struct acp_dev_data *adata) { struct snd_soc_acpi_mach *mach; @@ -137,17 +177,20 @@ static irqreturn_t i2s_irq_handler(int irq, void *data) void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream) { struct acp_resource *rsrc = adata->rsrc; - u32 pte_reg, pte_size, reg_val; + u32 reg_val; - /* Use ATU base Group5 */ - pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_5; - pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5; + reg_val = rsrc->sram_pte_offset; stream->reg_offset = 0x02000000; - /* Group Enable */ - reg_val = rsrc->sram_pte_offset; - writel(reg_val | BIT(31), adata->acp_base + pte_reg); - writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + pte_size); + writel((reg_val + GRP1_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + + writel((reg_val + GRP2_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2); + writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2); + + writel(reg_val | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5); + writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5); + writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL); } EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, SND_SOC_ACP_COMMON); @@ -161,7 +204,40 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s u32 low, high, val; u16 page_idx; - val = stream->pte_offset; + switch (adata->platform) { + case ACP70: + case ACP71: + switch (stream->dai_id) { + case I2S_SP_INSTANCE: + if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + val = 0x0; + else + val = 0x1000; + break; + case I2S_BT_INSTANCE: + if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + val = 0x2000; + else + val = 0x3000; + break; + case I2S_HS_INSTANCE: + if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + val = 0x4000; + else + val = 0x5000; + break; + case DMIC_INSTANCE: + val = 0x6000; + break; + default: + dev_err(adata->dev, "Invalid dai id %x\n", stream->dai_id); + return; + } + break; + default: + val = stream->pte_offset; + break; + } for (page_idx = 0; page_idx < num_pages; page_idx++) { /* Load the low address of page int ACP SRAM through SRBM */ @@ -183,6 +259,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs struct snd_pcm_runtime *runtime = substream->runtime; struct device *dev = component->dev; struct acp_dev_data *adata = dev_get_drvdata(dev); + struct acp_chip_info *chip; struct acp_stream *stream; int ret; @@ -191,11 +268,37 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs return -ENOMEM; stream->substream = substream; + chip = dev_get_platdata(dev); + switch (chip->acp_rev) { + case ACP63_DEV: + case ACP70_DEV: + case ACP71_DEV: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp6x_pcm_hardware_playback; + else + runtime->hw = acp6x_pcm_hardware_capture; + break; + default: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp_pcm_hardware_playback; + else + runtime->hw = acp_pcm_hardware_capture; + break; + } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - runtime->hw = acp_pcm_hardware_playback; - else - runtime->hw = acp_pcm_hardware_capture; + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE); + if (ret) { + dev_err(component->dev, "set hw constraint HW_PARAM_PERIOD_BYTES failed\n"); + kfree(stream); + return ret; + } + + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, DMA_SIZE); + if (ret) { + dev_err(component->dev, "set hw constraint HW_PARAM_BUFFER_BYTES failed\n"); + kfree(stream); + return ret; + } ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) { diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c index 158f819f8da4..396434a45eea 100644 --- a/sound/soc/amd/acp/acp-rembrandt.c +++ b/sound/soc/amd/acp/acp-rembrandt.c @@ -39,8 +39,6 @@ static struct acp_resource rsrc = { .irqp_used = 1, .soc_mclk = true, .irq_reg_offset = 0x1a00, - .i2s_pin_cfg_offset = 0x1440, - .i2s_mode = 0x0a, .scratch_reg_offset = 0x12800, .sram_pte_offset = 0x03802800, }; @@ -231,12 +229,13 @@ static int rembrandt_audio_probe(struct platform_device *pdev) adata->rsrc = &rsrc; adata->platform = REMBRANDT; adata->flag = chip->flag; + adata->is_i2s_config = chip->is_i2s_config; adata->machines = snd_soc_acpi_amd_rmb_acp_machines; acp_machine_select(adata); dev_set_drvdata(dev, adata); - if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) { + if (chip->is_i2s_config && rsrc.soc_mclk) { ret = acp6x_master_clock_generate(dev); if (ret) return ret; @@ -269,7 +268,7 @@ static int __maybe_unused rmb_pcm_resume(struct device *dev) snd_pcm_uframes_t buf_in_frames; u64 buf_size; - if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC) + if (adata->is_i2s_config && adata->rsrc->soc_mclk) acp6x_master_clock_generate(dev); spin_lock(&adata->acp_lock); @@ -296,7 +295,7 @@ static const struct dev_pm_ops rmb_dma_pm_ops = { static struct platform_driver rembrandt_driver = { .probe = rembrandt_audio_probe, - .remove_new = rembrandt_audio_remove, + .remove = rembrandt_audio_remove, .driver = { .name = "acp_asoc_rembrandt", .pm = &rmb_dma_pm_ops, diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c index b0e181c9a733..5e3f730aa6bf 100644 --- a/sound/soc/amd/acp/acp-renoir.c +++ b/sound/soc/amd/acp/acp-renoir.c @@ -32,8 +32,6 @@ static struct acp_resource rsrc = { .no_of_ctrls = 1, .irqp_used = 0, .irq_reg_offset = 0x1800, - .i2s_pin_cfg_offset = 0x1400, - .i2s_mode = 0x04, .scratch_reg_offset = 0x12800, .sram_pte_offset = 0x02052800, }; @@ -246,7 +244,7 @@ static const struct dev_pm_ops rn_dma_pm_ops = { static struct platform_driver renoir_driver = { .probe = renoir_audio_probe, - .remove_new = renoir_audio_remove, + .remove = renoir_audio_remove, .driver = { .name = "acp_asoc_renoir", .pm = &rn_dma_pm_ops, diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c new file mode 100644 index 000000000000..306854fb08e3 --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2024 Advanced Micro Devices, Inc. + +/* + * acp-sdw-sof-mach - ASoC Machine driver for AMD SoundWire platforms + */ + +#include <linux/bitmap.h> +#include <linux/device.h> +#include <linux/dmi.h> +#include <linux/module.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "soc_amd_sdw_common.h" +#include "../../codecs/rt711.h" + +static unsigned long sof_sdw_quirk = RT711_JD1; +static int quirk_override = -1; +module_param_named(quirk, quirk_override, int, 0444); +MODULE_PARM_DESC(quirk, "Board-specific quirk override"); + +static void log_quirks(struct device *dev) +{ + if (SOC_JACK_JDSRC(sof_sdw_quirk)) + dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", + SOC_JACK_JDSRC(sof_sdw_quirk)); + if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC) + dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n"); +} + +static int sof_sdw_quirk_cb(const struct dmi_system_id *id) +{ + sof_sdw_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id sof_sdw_quirk_table[] = { + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AMD"), + DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"), + }, + .driver_data = (void *)RT711_JD2, + }, + {} +}; + +static struct snd_soc_dai_link_component platform_component[] = { + { + /* name might be overridden during probe */ + .name = "0000:04:00.5", + } +}; + +static const struct snd_soc_ops sdw_ops = { + .startup = asoc_sdw_startup, + .prepare = asoc_sdw_prepare, + .trigger = asoc_sdw_trigger, + .hw_params = asoc_sdw_hw_params, + .hw_free = asoc_sdw_hw_free, + .shutdown = asoc_sdw_shutdown, +}; + +static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) +{ + switch (sdw_link_id) { + case AMD_SDW0: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO0_RX; + break; + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO1_TX; + break; + case SOC_SDW_AMP_IN_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO1_RX; + break; + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO2_RX; + break; + default: + dev_err(dev, "Invalid be id:%d\n", be_id); + return -EINVAL; + } + break; + case AMD_SDW1: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW1_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + case SOC_SDW_AMP_IN_DAI_ID: + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP63_SW1_AUDIO0_RX; + break; + default: + dev_err(dev, "invalid be_id:%d\n", be_id); + return -EINVAL; + } + break; + default: + dev_err(dev, "Invalid link id:%d\n", sdw_link_id); + return -EINVAL; + } + return 0; +} + +static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; + +static int create_sdw_dailink(struct snd_soc_card *card, + struct asoc_sdw_dailink *sof_dai, + struct snd_soc_dai_link **dai_links, + int *be_id, struct snd_soc_codec_conf **codec_conf) +{ + struct device *dev = card->dev; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; + struct asoc_sdw_endpoint *sof_end; + int cpu_pin_id; + int stream; + int ret; + + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { + if (sof_end->name_prefix) { + (*codec_conf)->dlc.name = sof_end->codec_name; + (*codec_conf)->name_prefix = sof_end->name_prefix; + (*codec_conf)++; + } + + if (sof_end->include_sidecar) { + ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf); + if (ret) + return ret; + } + } + + for_each_pcm_streams(stream) { + static const char * const sdw_stream_name[] = { + "SDW%d-PIN%d-PLAYBACK", + "SDW%d-PIN%d-CAPTURE", + "SDW%d-PIN%d-PLAYBACK-%s", + "SDW%d-PIN%d-CAPTURE-%s", + }; + struct snd_soc_dai_link_ch_map *codec_maps; + struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *cpus; + int num_cpus = hweight32(sof_dai->link_mask[stream]); + int num_codecs = sof_dai->num_devs[stream]; + int playback, capture; + int i = 0, j = 0; + char *name; + + if (!sof_dai->num_devs[stream]) + continue; + + sof_end = list_first_entry(&sof_dai->endpoints, + struct asoc_sdw_endpoint, list); + + *be_id = sof_end->dai_info->dailink[stream]; + if (*be_id < 0) { + dev_err(dev, "Invalid dailink id %d\n", *be_id); + return -EINVAL; + } + + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + ret = get_acp63_cpu_pin_id(ffs(sof_end->link_mask - 1), + *be_id, &cpu_pin_id, dev); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + /* create stream name according to first link id */ + if (ctx->append_dai_type) { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream + 2], + ffs(sof_end->link_mask) - 1, + cpu_pin_id, + type_strings[sof_end->dai_info->dai_type]); + } else { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], + ffs(sof_end->link_mask) - 1, + cpu_pin_id); + } + if (!name) + return -ENOMEM; + + cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); + if (!cpus) + return -ENOMEM; + + codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); + if (!codecs) + return -ENOMEM; + + codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); + if (!codec_maps) + return -ENOMEM; + + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { + if (!sof_end->dai_info->direction[stream]) + continue; + + int link_num = ffs(sof_end->link_mask) - 1; + + cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW%d Pin%d", + link_num, cpu_pin_id); + dev_dbg(dev, "cpu[%d].dai_name:%s\n", i, cpus[i].dai_name); + if (!cpus[i].dai_name) + return -ENOMEM; + + codec_maps[j].cpu = i; + codec_maps[j].codec = j; + + codecs[j].name = sof_end->codec_name; + codecs[j].dai_name = sof_end->dai_info->dai_name; + j++; + } + + WARN_ON(j != num_codecs); + + playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); + capture = (stream == SNDRV_PCM_STREAM_CAPTURE); + + asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, + cpus, num_cpus, platform_component, + ARRAY_SIZE(platform_component), codecs, num_codecs, + asoc_sdw_rtd_init, &sdw_ops); + + /* + * SoundWire DAILINKs use 'stream' functions and Bank Switch operations + * based on wait_for_completion(), tag them as 'nonatomic'. + */ + (*dai_links)->nonatomic = true; + (*dai_links)->ch_maps = codec_maps; + + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { + if (sof_end->dai_info->init) + sof_end->dai_info->init(card, *dai_links, + sof_end->codec_info, + playback); + } + + (*dai_links)++; + } + + return 0; +} + +static int create_sdw_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + struct asoc_sdw_dailink *sof_dais, + struct snd_soc_codec_conf **codec_conf) +{ + int ret; + + /* generate DAI links by each sdw link */ + while (sof_dais->initialised) { + int current_be_id; + + ret = create_sdw_dailink(card, sof_dais, dai_links, + ¤t_be_id, codec_conf); + if (ret) + return ret; + + /* Update the be_id to match the highest ID used for SDW link */ + if (*be_id < current_be_id) + *be_id = current_be_id; + + sof_dais++; + } + + return 0; +} + +static int create_dmic_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id) +{ + struct device *dev = card->dev; + int ret; + + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec", + 0, 1, // DMIC only supports capture + "acp-sof-dmic", platform_component->name, + ARRAY_SIZE(platform_component), + "dmic-codec", "dmic-hifi", + asoc_sdw_dmic_init, NULL); + if (ret) + return ret; + + (*dai_links)++; + + return 0; +} + +static int sof_card_dai_links_create(struct snd_soc_card *card) +{ + struct device *dev = card->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); + int sdw_be_num = 0, dmic_num = 0; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + struct snd_soc_codec_conf *codec_conf; + struct asoc_sdw_endpoint *sof_ends; + struct asoc_sdw_dailink *sof_dais; + struct snd_soc_dai_link *dai_links; + int num_devs = 0; + int num_ends = 0; + int num_links; + int be_id = 0; + int ret; + + ret = asoc_sdw_count_sdw_endpoints(card, &num_devs, &num_ends); + if (ret < 0) { + dev_err(dev, "failed to count devices/endpoints: %d\n", ret); + return ret; + } + + /* One per DAI link, worst case is a DAI link for every endpoint */ + sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL); + if (!sof_dais) + return -ENOMEM; + + /* One per endpoint, ie. each DAI on each codec/amp */ + sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL); + if (!sof_ends) { + ret = -ENOMEM; + goto err_dai; + } + + ret = asoc_sdw_parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs); + if (ret < 0) + goto err_end; + + sdw_be_num = ret; + + /* enable dmic */ + if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num) + dmic_num = 1; + + dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num); + + codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); + if (!codec_conf) { + ret = -ENOMEM; + goto err_end; + } + + /* allocate BE dailinks */ + num_links = sdw_be_num + dmic_num; + dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); + if (!dai_links) { + ret = -ENOMEM; + goto err_end; + } + + card->codec_conf = codec_conf; + card->num_configs = num_devs; + card->dai_link = dai_links; + card->num_links = num_links; + + /* SDW */ + if (sdw_be_num) { + ret = create_sdw_dailinks(card, &dai_links, &be_id, + sof_dais, &codec_conf); + if (ret) + goto err_end; + } + + /* dmic */ + if (dmic_num > 0) { + if (ctx->ignore_internal_dmic) { + dev_warn(dev, "Ignoring ACP DMIC\n"); + } else { + ret = create_dmic_dailinks(card, &dai_links, &be_id); + if (ret) + goto err_end; + } + } + + WARN_ON(codec_conf != card->codec_conf + card->num_configs); + WARN_ON(dai_links != card->dai_link + card->num_links); + +err_end: + kfree(sof_ends); +err_dai: + kfree(sof_dais); + + return ret; +} + +static int mc_probe(struct platform_device *pdev) +{ + struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); + struct snd_soc_card *card; + struct amd_mc_ctx *amd_ctx; + struct asoc_sdw_mc_private *ctx; + int amp_num = 0, i; + int ret; + + amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL); + if (!amd_ctx) + return -ENOMEM; + + amd_ctx->acp_rev = mach->mach_params.subsystem_rev; + amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS; + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count(); + ctx->private = amd_ctx; + card = &ctx->card; + card->dev = &pdev->dev; + card->name = "amd-soundwire"; + card->owner = THIS_MODULE; + card->late_probe = asoc_sdw_card_late_probe; + + snd_soc_card_set_drvdata(card, ctx); + + dmi_check_system(sof_sdw_quirk_table); + + if (quirk_override != -1) { + dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", + sof_sdw_quirk, quirk_override); + sof_sdw_quirk = quirk_override; + } + + log_quirks(card->dev); + + ctx->mc_quirk = sof_sdw_quirk; + /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ + for (i = 0; i < ctx->codec_info_list_count; i++) + codec_info_list[i].amp_num = 0; + + ret = sof_card_dai_links_create(card); + if (ret < 0) + return ret; + + /* + * the default amp_num is zero for each codec and + * amp_num will only be increased for active amp + * codecs on used platform + */ + for (i = 0; i < ctx->codec_info_list_count; i++) + amp_num += codec_info_list[i].amp_num; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + " cfg-amp:%d", amp_num); + if (!card->components) + return -ENOMEM; + + /* Register the card */ + ret = devm_snd_soc_register_card(card->dev, card); + if (ret) { + dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret); + asoc_sdw_mc_dailink_exit_loop(card); + return ret; + } + + platform_set_drvdata(pdev, card); + + return ret; +} + +static void mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + asoc_sdw_mc_dailink_exit_loop(card); +} + +static const struct platform_device_id mc_id_table[] = { + { "amd_sof_sdw", }, + {} +}; +MODULE_DEVICE_TABLE(platform, mc_id_table); + +static struct platform_driver sof_sdw_driver = { + .driver = { + .name = "amd_sof_sdw", + .pm = &snd_soc_pm_ops, + }, + .probe = mc_probe, + .remove = mc_remove, + .id_table = mc_id_table, +}; + +module_platform_driver(sof_sdw_driver); + +MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver"); +MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c index fc59ea34e687..f36750167fa2 100644 --- a/sound/soc/amd/acp/acp-sof-mach.c +++ b/sound/soc/amd/acp/acp-sof-mach.c @@ -158,6 +158,8 @@ static const struct platform_device_id board_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(platform, board_ids); + static struct platform_driver acp_asoc_audio = { .driver = { .name = "sof_mach", @@ -171,11 +173,4 @@ module_platform_driver(acp_asoc_audio); MODULE_IMPORT_NS(SND_SOC_AMD_MACH); MODULE_DESCRIPTION("ACP SOF Machine Driver"); -MODULE_ALIAS("platform:rt5682-rt1019"); -MODULE_ALIAS("platform:rt5682-max"); -MODULE_ALIAS("platform:rt5682s-max"); -MODULE_ALIAS("platform:rt5682s-rt1019"); -MODULE_ALIAS("platform:nau8825-max"); -MODULE_ALIAS("platform:rt5682s-hs-rt1019"); -MODULE_ALIAS("platform:nau8821-max"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c index 4d342441a650..f325c374f228 100644 --- a/sound/soc/amd/acp/acp63.c +++ b/sound/soc/amd/acp/acp63.c @@ -55,8 +55,6 @@ static struct acp_resource rsrc = { .irqp_used = 1, .soc_mclk = true, .irq_reg_offset = 0x1a00, - .i2s_pin_cfg_offset = 0x1440, - .i2s_mode = 0x0a, .scratch_reg_offset = 0x12800, .sram_pte_offset = 0x03802800, }; @@ -241,11 +239,12 @@ static int acp63_audio_probe(struct platform_device *pdev) adata->rsrc = &rsrc; adata->platform = ACP63; adata->flag = chip->flag; + adata->is_i2s_config = chip->is_i2s_config; adata->machines = snd_soc_acpi_amd_acp63_acp_machines; acp_machine_select(adata); dev_set_drvdata(dev, adata); - if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) { + if (chip->is_i2s_config && rsrc.soc_mclk) { ret = acp63_i2s_master_clock_generate(adata); if (ret) return ret; @@ -278,7 +277,7 @@ static int __maybe_unused acp63_pcm_resume(struct device *dev) snd_pcm_uframes_t buf_in_frames; u64 buf_size; - if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC) + if (adata->is_i2s_config && adata->rsrc->soc_mclk) acp63_i2s_master_clock_generate(adata); spin_lock(&adata->acp_lock); @@ -305,7 +304,7 @@ static const struct dev_pm_ops acp63_dma_pm_ops = { static struct platform_driver acp63_driver = { .probe = acp63_audio_probe, - .remove_new = acp63_audio_remove, + .remove = acp63_audio_remove, .driver = { .name = "acp_asoc_acp63", .pm = &acp63_dma_pm_ops, diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 0d7cdd4017e5..68d2590e1a4e 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -25,16 +25,17 @@ #define DRV_NAME "acp_asoc_acp70" +#define CLK7_CLK0_DFS_CNTL_N1 0X0006C1A4 +#define CLK0_DIVIDER 0X19 + static struct acp_resource rsrc = { .offset = 0, .no_of_ctrls = 2, .irqp_used = 1, .soc_mclk = true, .irq_reg_offset = 0x1a00, - .i2s_pin_cfg_offset = 0x1440, - .i2s_mode = 0x0a, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x03802800, + .scratch_reg_offset = 0x10000, + .sram_pte_offset = 0x03800000, }; static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = { @@ -51,23 +52,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_SP_INSTANCE, .playback = { .stream_name = "I2S SP Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S SP Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 2, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, }, @@ -76,23 +77,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_BT_INSTANCE, .playback = { .stream_name = "I2S BT Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S BT Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 2, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, }, @@ -101,23 +102,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_HS_INSTANCE, .playback = { .stream_name = "I2S HS Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S HS Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, }, @@ -136,12 +137,36 @@ static struct snd_soc_dai_driver acp70_dai[] = { }, }; +static int acp70_i2s_master_clock_generate(struct acp_dev_data *adata) +{ + struct pci_dev *smn_dev; + u32 device_id; + + if (adata->platform == ACP70) + device_id = 0x1507; + else if (adata->platform == ACP71) + device_id = 0x1122; + else + return -ENODEV; + + smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, device_id, NULL); + + if (!smn_dev) + return -ENODEV; + + /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/ + smn_write(smn_dev, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER); + + return 0; +} + static int acp_acp70_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_chip_info *chip; struct acp_dev_data *adata; struct resource *res; + int ret; chip = dev_get_platdata(&pdev->dev); if (!chip || !chip->base) { @@ -149,7 +174,11 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) return -ENODEV; } - if (chip->acp_rev != ACP70_DEV) { + switch (chip->acp_rev) { + case ACP70_DEV: + case ACP71_DEV: + break; + default: dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); return -ENODEV; } @@ -180,11 +209,21 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) adata->num_dai = ARRAY_SIZE(acp70_dai); adata->rsrc = &rsrc; adata->machines = snd_soc_acpi_amd_acp70_acp_machines; - adata->platform = ACP70; + if (chip->acp_rev == ACP70_DEV) + adata->platform = ACP70; + else + adata->platform = ACP71; + adata->flag = chip->flag; acp_machine_select(adata); dev_set_drvdata(dev, adata); + + ret = acp70_i2s_master_clock_generate(adata); + if (ret) { + dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n"); + return ret; + } acp_enable_interrupts(adata); acp_platform_register(dev); pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); @@ -239,7 +278,7 @@ static const struct dev_pm_ops acp70_dma_pm_ops = { static struct platform_driver acp70_driver = { .probe = acp_acp70_audio_probe, - .remove_new = acp_acp70_audio_remove, + .remove = acp_acp70_audio_remove, .driver = { .name = "acp_asoc_acp70", .pm = &acp70_dma_pm_ops, diff --git a/sound/soc/amd/acp/amd-acp63-acpi-match.c b/sound/soc/amd/acp/amd-acp63-acpi-match.c new file mode 100644 index 000000000000..be9367913073 --- /dev/null +++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * amd-acp63-acpi-match.c - tables and support for ACP 6.3 platform + * ACPI enumeration. + * + * Copyright 2024 Advanced Micro Devices, Inc. + */ + +#include <sound/soc-acpi.h> +#include "../mach-config.h" + +static const struct snd_soc_acpi_endpoint single_endpoint = { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0 +}; + +static const struct snd_soc_acpi_endpoint spk_l_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 0, + .group_id = 1 +}; + +static const struct snd_soc_acpi_endpoint spk_r_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 1, + .group_id = 1 +}; + +static const struct snd_soc_acpi_adr_device rt711_rt1316_group_adr[] = { + { + .adr = 0x000030025D071101ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt711" + }, + { + .adr = 0x000030025D131601ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "rt1316-1" + }, + { + .adr = 0x000032025D131601ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1316-2" + }, +}; + +static const struct snd_soc_acpi_adr_device rt714_adr[] = { + { + .adr = 0x130025d071401ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt714" + } +}; + +static const struct snd_soc_acpi_link_adr acp63_4_in_1_sdca[] = { + { .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_rt1316_group_adr), + .adr_d = rt711_rt1316_group_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt714_adr), + .adr_d = rt714_adr, + }, + {} +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = { + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_4_in_1_sdca, + .drv_name = "amd_sof_sdw", + .sof_tplg_filename = "sof-acp_6_3-rt711-l0-rt1316-l0-rt714-l1.tplg", + .fw_filename = "sof-acp_6_3.ri", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_sdw_machines); + +MODULE_DESCRIPTION("AMD ACP6.3 tables and support for ACPI enumeration"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index d75b4eb34de8..854269fea875 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -22,6 +22,7 @@ #define ACP6X_DEV 6 #define ACP63_DEV 0x63 #define ACP70_DEV 0x70 +#define ACP71_DEV 0x71 #define DMIC_INSTANCE 0x00 #define I2S_SP_INSTANCE 0x01 @@ -61,6 +62,14 @@ #define I2S_HS_TX_MEM_WINDOW_START 0x40A0000 #define I2S_HS_RX_MEM_WINDOW_START 0x40C0000 +#define ACP7x_I2S_SP_TX_MEM_WINDOW_START 0x4000000 +#define ACP7x_I2S_SP_RX_MEM_WINDOW_START 0x4200000 +#define ACP7x_I2S_BT_TX_MEM_WINDOW_START 0x4400000 +#define ACP7x_I2S_BT_RX_MEM_WINDOW_START 0x4600000 +#define ACP7x_I2S_HS_TX_MEM_WINDOW_START 0x4800000 +#define ACP7x_I2S_HS_RX_MEM_WINDOW_START 0x4A00000 +#define ACP7x_DMIC_MEM_WINDOW_START 0x4C00000 + #define SP_PB_FIFO_ADDR_OFFSET 0x500 #define SP_CAPT_FIFO_ADDR_OFFSET 0x700 #define BT_PB_FIFO_ADDR_OFFSET 0x900 @@ -103,6 +112,8 @@ #define ACP70_PGFSM_CONTROL ACP6X_PGFSM_CONTROL #define ACP70_PGFSM_STATUS ACP6X_PGFSM_STATUS +#define ACP_ZSC_DSP_CTRL 0x0001014 +#define ACP_ZSC_STS 0x0001018 #define ACP_SOFT_RST_DONE_MASK 0x00010001 #define ACP_PGFSM_CNTL_POWER_ON_MASK 0xffffffff @@ -162,8 +173,6 @@ struct acp_resource { int irqp_used; bool soc_mclk; u32 irq_reg_offset; - u32 i2s_pin_cfg_offset; - int i2s_mode; u64 scratch_reg_offset; u64 sram_pte_offset; }; @@ -175,6 +184,7 @@ struct acp_dev_data { unsigned int i2s_irq; bool tdm_mode; + bool is_i2s_config; /* SOC specific dais */ struct snd_soc_dai_driver *dai_driver; int num_dai; @@ -257,12 +267,12 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int if (direction == SNDRV_PCM_STREAM_PLAYBACK) { switch (dai_id) { case I2S_BT_INSTANCE: - high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW); + high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(adata)); + low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW(adata)); break; case I2S_SP_INSTANCE: - high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW); + high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(adata)); + low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(adata)); break; case I2S_HS_INSTANCE: high = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH); @@ -275,12 +285,12 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int } else { switch (dai_id) { case I2S_BT_INSTANCE: - high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW); + high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(adata)); + low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW(adata)); break; case I2S_SP_INSTANCE: - high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW); + high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(adata)); + low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(adata)); break; case I2S_HS_INSTANCE: high = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH); diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h index 18da734c0e9e..117ea63e85c6 100644 --- a/sound/soc/amd/acp/chip_offset_byte.h +++ b/sound/soc/amd/acp/chip_offset_byte.h @@ -12,9 +12,16 @@ #define _ACP_IP_OFFSET_HEADER #define ACPAXI2AXI_ATU_CTRL 0xC40 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0xC00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0xC04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0xC08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0xC0C #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0xC20 #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0xC24 +#define GRP1_OFFSET 0x0 +#define GRP2_OFFSET 0x4000 + #define ACP_PGFSM_CONTROL 0x141C #define ACP_PGFSM_STATUS 0x1420 #define ACP_SOFT_RESET 0x1000 @@ -32,42 +39,47 @@ /* Registers from ACP_AUDIO_BUFFERS block */ -#define ACP_I2S_RX_RINGBUFADDR 0x2000 -#define ACP_I2S_RX_RINGBUFSIZE 0x2004 -#define ACP_I2S_RX_LINKPOSITIONCNTR 0x2008 -#define ACP_I2S_RX_FIFOADDR 0x200C -#define ACP_I2S_RX_FIFOSIZE 0x2010 -#define ACP_I2S_RX_DMA_SIZE 0x2014 -#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x2018 -#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x201C -#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x2020 -#define ACP_I2S_TX_RINGBUFADDR 0x2024 -#define ACP_I2S_TX_RINGBUFSIZE 0x2028 -#define ACP_I2S_TX_LINKPOSITIONCNTR 0x202C -#define ACP_I2S_TX_FIFOADDR 0x2030 -#define ACP_I2S_TX_FIFOSIZE 0x2034 -#define ACP_I2S_TX_DMA_SIZE 0x2038 -#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x203C -#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x2040 -#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x2044 -#define ACP_BT_RX_RINGBUFADDR 0x2048 -#define ACP_BT_RX_RINGBUFSIZE 0x204C -#define ACP_BT_RX_LINKPOSITIONCNTR 0x2050 -#define ACP_BT_RX_FIFOADDR 0x2054 -#define ACP_BT_RX_FIFOSIZE 0x2058 -#define ACP_BT_RX_DMA_SIZE 0x205C -#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x2060 -#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x2064 -#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x2068 -#define ACP_BT_TX_RINGBUFADDR 0x206C -#define ACP_BT_TX_RINGBUFSIZE 0x2070 -#define ACP_BT_TX_LINKPOSITIONCNTR 0x2074 -#define ACP_BT_TX_FIFOADDR 0x2078 -#define ACP_BT_TX_FIFOSIZE 0x207C -#define ACP_BT_TX_DMA_SIZE 0x2080 -#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x2084 -#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x2088 -#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x208C +#define ACP_I2S_REG_ADDR(acp_adata, addr) \ + ((addr) + (acp_adata->rsrc->irqp_used * \ + acp_adata->rsrc->irq_reg_offset)) + +#define ACP_I2S_RX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2000) +#define ACP_I2S_RX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2004) +#define ACP_I2S_RX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2008) +#define ACP_I2S_RX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x200C) +#define ACP_I2S_RX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2010) +#define ACP_I2S_RX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2014) +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2018) +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x201C) +#define ACP_I2S_RX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2020) +#define ACP_I2S_TX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2024) +#define ACP_I2S_TX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2028) +#define ACP_I2S_TX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x202C) +#define ACP_I2S_TX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2030) +#define ACP_I2S_TX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2034) +#define ACP_I2S_TX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2038) +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x203C) +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2040) +#define ACP_I2S_TX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2044) +#define ACP_BT_RX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2048) +#define ACP_BT_RX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x204C) +#define ACP_BT_RX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2050) +#define ACP_BT_RX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2054) +#define ACP_BT_RX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2058) +#define ACP_BT_RX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x205C) +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2060) +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2064) +#define ACP_BT_RX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2068) +#define ACP_BT_TX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x206C) +#define ACP_BT_TX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2070) +#define ACP_BT_TX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2074) +#define ACP_BT_TX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2078) +#define ACP_BT_TX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x207C) +#define ACP_BT_TX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2080) +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2084) +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2088) +#define ACP_BT_TX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x208C) + #define ACP_HS_RX_RINGBUFADDR 0x3A90 #define ACP_HS_RX_RINGBUFSIZE 0x3A94 #define ACP_HS_RX_LINKPOSITIONCNTR 0x3A98 diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h new file mode 100644 index 000000000000..f1bd5a7afc8e --- /dev/null +++ b/sound/soc/amd/acp/soc_amd_sdw_common.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved + */ + +/* + * soc_amd_sdw_common.h - prototypes for common helpers + */ + +#ifndef SOC_AMD_SDW_COMMON_H +#define SOC_AMD_SDW_COMMON_H + +#include <linux/bits.h> +#include <linux/types.h> +#include <sound/soc.h> +#include <sound/soc_sdw_utils.h> + +#define ACP63_SDW_MAX_CPU_DAIS 8 +#define ACP63_SDW_MAX_LINKS 2 + +#define AMD_SDW_MAX_GROUPS 9 +#define ACP63_PCI_REV 0x63 +#define SOC_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) +#define ASOC_SDW_FOUR_SPK BIT(4) +#define ASOC_SDW_ACP_DMIC BIT(5) + +#define AMD_SDW0 0 +#define AMD_SDW1 1 +#define ACP63_SW0_AUDIO0_TX 0 +#define ACP63_SW0_AUDIO1_TX 1 +#define ACP63_SW0_AUDIO2_TX 2 + +#define ACP63_SW0_AUDIO0_RX 3 +#define ACP63_SW0_AUDIO1_RX 4 +#define ACP63_SW0_AUDIO2_RX 5 + +#define ACP63_SW1_AUDIO0_TX 0 +#define ACP63_SW1_AUDIO0_RX 1 + +struct amd_mc_ctx { + unsigned int acp_rev; + unsigned int max_sdw_links; +}; + +#endif diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h index 7af0f9cf3921..1a967da35a0f 100644 --- a/sound/soc/amd/mach-config.h +++ b/sound/soc/amd/mach-config.h @@ -23,6 +23,8 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sof_machines[]; struct config_entry { u32 flags; diff --git a/sound/soc/amd/ps/ps-mach.c b/sound/soc/amd/ps/ps-mach.c index e675b8f569eb..ff8ad036b077 100644 --- a/sound/soc/amd/ps/ps-mach.c +++ b/sound/soc/amd/ps/ps-mach.c @@ -75,5 +75,6 @@ static struct platform_driver acp63_mach_driver = { module_platform_driver(acp63_mach_driver); MODULE_AUTHOR("Syed.SabaKareem@amd.com"); +MODULE_DESCRIPTION("AMD Pink Sardine support for DMIC"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c index 7bbacbab1095..318fc260f293 100644 --- a/sound/soc/amd/ps/ps-pdm-dma.c +++ b/sound/soc/amd/ps/ps-pdm-dma.c @@ -448,7 +448,7 @@ static const struct dev_pm_ops acp63_pdm_pm_ops = { static struct platform_driver acp63_pdm_dma_driver = { .probe = acp63_pdm_audio_probe, - .remove_new = acp63_pdm_audio_remove, + .remove = acp63_pdm_audio_remove, .driver = { .name = "acp_ps_pdm_dma", .pm = &acp63_pdm_pm_ops, diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 2f630753278d..3b4b9c6b3171 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -551,7 +551,7 @@ static const struct dev_pm_ops acp63_pm_ops = { static struct platform_driver acp63_sdw_dma_driver = { .probe = acp63_sdw_platform_probe, - .remove_new = acp63_sdw_platform_remove, + .remove = acp63_sdw_platform_remove, .driver = { .name = "amd_ps_sdw_dma", .pm = &acp63_pm_ops, diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index 3a50558f6751..bb9ed52d744d 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -509,7 +509,7 @@ static const struct dev_pm_ops acp3x_pm_ops = { static struct platform_driver acp3x_dma_driver = { .probe = acp3x_audio_probe, - .remove_new = acp3x_audio_remove, + .remove = acp3x_audio_remove, .driver = { .name = "acp3x_rv_i2s_dma", .pm = &acp3x_pm_ops, diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index c3b47e9bd239..95ac8c680037 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -489,7 +489,7 @@ static const struct dev_pm_ops acp_pdm_pm_ops = { static struct platform_driver acp_pdm_dma_driver = { .probe = acp_pdm_audio_probe, - .remove_new = acp_pdm_audio_remove, + .remove = acp_pdm_audio_remove, .driver = { .name = "acp_rn_pdm_dma", .pm = &acp_pdm_pm_ops, diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c index 5d979a7b77fb..3249f74a0197 100644 --- a/sound/soc/amd/renoir/acp3x-rn.c +++ b/sound/soc/amd/renoir/acp3x-rn.c @@ -72,5 +72,6 @@ static struct platform_driver acp_mach_driver = { module_platform_driver(acp_mach_driver); MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD Renoir support for DMIC"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c index 491b16e52a72..d5965f2b09bc 100644 --- a/sound/soc/amd/vangogh/acp5x-pcm-dma.c +++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c @@ -499,7 +499,7 @@ static const struct dev_pm_ops acp5x_pm_ops = { static struct platform_driver acp5x_dma_driver = { .probe = acp5x_audio_probe, - .remove_new = acp5x_audio_remove, + .remove = acp5x_audio_remove, .driver = { .name = "acp5x_i2s_dma", .pm = &acp5x_pm_ops, diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 1760b5d42460..438865d5e376 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -224,6 +224,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { .driver_data = &acp6x_card, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21M3"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21M5"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_NAME, "82QF"), } }, @@ -283,6 +297,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "M5602RA"), + } + }, { .driver_data = &acp6x_card, .matches = { @@ -308,6 +329,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { .driver_data = &acp6x_card, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "E1404FA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA"), } }, @@ -321,6 +349,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { { .driver_data = &acp6x_card, .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "M3502RA"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 B7ED"), } @@ -335,6 +370,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { { .driver_data = &acp6x_card, .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 17 D7VEK"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"), DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), } @@ -399,6 +441,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { .driver_data = &acp6x_card, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A44"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), DMI_MATCH(DMI_BOARD_NAME, "8A22"), } }, @@ -413,6 +462,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { .driver_data = &acp6x_card, .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A7F"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8B27"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), DMI_MATCH(DMI_BOARD_NAME, "8B2F"), } }, @@ -504,5 +567,6 @@ static struct platform_driver acp6x_mach_driver = { module_platform_driver(acp6x_mach_driver); MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD Yellow Carp support for DMIC"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/yc/acp6x-pdm-dma.c b/sound/soc/amd/yc/acp6x-pdm-dma.c index 72c4591e451b..3eb3e82efb10 100644 --- a/sound/soc/amd/yc/acp6x-pdm-dma.c +++ b/sound/soc/amd/yc/acp6x-pdm-dma.c @@ -440,7 +440,7 @@ static const struct dev_pm_ops acp6x_pdm_pm_ops = { static struct platform_driver acp6x_pdm_dma_driver = { .probe = acp6x_pdm_audio_probe, - .remove_new = acp6x_pdm_audio_remove, + .remove = acp6x_pdm_audio_remove, .driver = { .name = "acp_yc_pdm_dma", .pm = &acp6x_pdm_pm_ops, |