2022-08-12 13:22:06

by Saba Kareem, Syed

[permalink] [raw]
Subject: [PATCH 07/13] ASoC: amd: add acp6.2 pdm driver dma ops

This patch adds PDM driver DMA operations for Pink Sardine Platform.

Signed-off-by: Syed Saba Kareem <[email protected]>
---
sound/soc/amd/ps/acp62.h | 41 +++++
sound/soc/amd/ps/ps-pdm-dma.c | 310 ++++++++++++++++++++++++++++++++++
2 files changed, 351 insertions(+)

diff --git a/sound/soc/amd/ps/acp62.h b/sound/soc/amd/ps/acp62.h
index 563252834b09..525e8bd225a2 100644
--- a/sound/soc/amd/ps/acp62.h
+++ b/sound/soc/amd/ps/acp62.h
@@ -27,6 +27,31 @@
#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
#define PDM_DMA_STAT 0x10

+#define PDM_DMA_INTR_MASK 0x10000
+#define ACP_ERROR_STAT 29
+#define PDM_DECIMATION_FACTOR 2
+#define ACP_PDM_CLK_FREQ_MASK 7
+#define ACP_WOV_MISC_CTRL_MASK 0x10
+#define ACP_PDM_ENABLE 1
+#define ACP_PDM_DISABLE 0
+#define ACP_PDM_DMA_EN_STATUS 2
+#define TWO_CH 2
+#define DELAY_US 5
+#define ACP_COUNTER 20000
+
+#define ACP_SRAM_PTE_OFFSET 0x03800000
+#define PAGE_SIZE_4K_ENABLE 2
+#define PDM_PTE_OFFSET 0
+#define PDM_MEM_WINDOW_START 0x4000000
+
+#define CAPTURE_MIN_NUM_PERIODS 4
+#define CAPTURE_MAX_NUM_PERIODS 4
+#define CAPTURE_MAX_PERIOD_SIZE 8192
+#define CAPTURE_MIN_PERIOD_SIZE 4096
+
+#define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS)
+#define MIN_BUFFER MAX_BUFFER
+
enum acp_config {
ACP_CONFIG_0 = 0,
ACP_CONFIG_1,
@@ -46,6 +71,22 @@ enum acp_config {
ACP_CONFIG_15,
};

+struct pdm_stream_instance {
+ u16 num_pages;
+ u16 channels;
+ dma_addr_t dma_addr;
+ u64 bytescount;
+ void __iomem *acp62_base;
+};
+
+union acp_pdm_dma_count {
+ struct {
+ u32 low;
+ u32 high;
+ } bcount;
+ u64 bytescount;
+};
+
struct pdm_dev_data {
u32 pdm_irq;
void __iomem *acp62_base;
diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c
index bca2ac3e81f5..a98a2015015d 100644
--- a/sound/soc/amd/ps/ps-pdm-dma.c
+++ b/sound/soc/amd/ps/ps-pdm-dma.c
@@ -17,6 +17,310 @@

#define DRV_NAME "acp_ps_pdm_dma"

+static const struct snd_pcm_hardware acp62_pdm_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_S32_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .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,
+};
+
+static void acp62_init_pdm_ring_buffer(u32 physical_addr, u32 buffer_size,
+ u32 watermark_size, void __iomem *acp_base)
+{
+ acp62_writel(physical_addr, acp_base + ACP_WOV_RX_RINGBUFADDR);
+ acp62_writel(buffer_size, acp_base + ACP_WOV_RX_RINGBUFSIZE);
+ acp62_writel(watermark_size, acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
+ acp62_writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL);
+}
+
+static void acp62_enable_pdm_clock(void __iomem *acp_base)
+{
+ u32 pdm_clk_enable, pdm_ctrl;
+
+ pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK;
+ pdm_ctrl = 0x00;
+
+ acp62_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL);
+ pdm_ctrl = acp62_readl(acp_base + ACP_WOV_MISC_CTRL);
+ pdm_ctrl |= ACP_WOV_MISC_CTRL_MASK;
+ acp62_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL);
+}
+
+static void acp62_enable_pdm_interrupts(void __iomem *acp_base)
+{
+ u32 ext_int_ctrl;
+
+ ext_int_ctrl = acp62_readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
+ ext_int_ctrl |= PDM_DMA_INTR_MASK;
+ acp62_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL);
+}
+
+static void acp62_disable_pdm_interrupts(void __iomem *acp_base)
+{
+ u32 ext_int_ctrl;
+
+ ext_int_ctrl = acp62_readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
+ ext_int_ctrl &= ~PDM_DMA_INTR_MASK;
+ acp62_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL);
+}
+
+static bool acp62_check_pdm_dma_status(void __iomem *acp_base)
+{
+ bool pdm_dma_status;
+ u32 pdm_enable, pdm_dma_enable;
+
+ pdm_dma_status = false;
+ pdm_enable = acp62_readl(acp_base + ACP_WOV_PDM_ENABLE);
+ pdm_dma_enable = acp62_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ if ((pdm_enable & ACP_PDM_ENABLE) && (pdm_dma_enable & ACP_PDM_DMA_EN_STATUS))
+ pdm_dma_status = true;
+
+ return pdm_dma_status;
+}
+
+static int acp62_start_pdm_dma(void __iomem *acp_base)
+{
+ u32 pdm_enable;
+ u32 pdm_dma_enable;
+ int timeout;
+
+ pdm_enable = 0x01;
+ pdm_dma_enable = 0x01;
+
+ acp62_enable_pdm_clock(acp_base);
+ acp62_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE);
+ acp62_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ timeout = 0;
+ while (++timeout < ACP_COUNTER) {
+ pdm_dma_enable = acp62_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ if ((pdm_dma_enable & 0x02) == ACP_PDM_DMA_EN_STATUS)
+ return 0;
+ udelay(DELAY_US);
+ }
+ return -ETIMEDOUT;
+}
+
+static int acp62_stop_pdm_dma(void __iomem *acp_base)
+{
+ u32 pdm_enable, pdm_dma_enable;
+ int timeout;
+
+ pdm_enable = 0x00;
+ pdm_dma_enable = 0x00;
+
+ pdm_enable = acp62_readl(acp_base + ACP_WOV_PDM_ENABLE);
+ pdm_dma_enable = acp62_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ if (pdm_dma_enable & 0x01) {
+ pdm_dma_enable = 0x02;
+ acp62_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ timeout = 0;
+ while (++timeout < ACP_COUNTER) {
+ pdm_dma_enable = acp62_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ if ((pdm_dma_enable & 0x02) == 0x00)
+ break;
+ udelay(DELAY_US);
+ }
+ if (timeout == ACP_COUNTER)
+ return -ETIMEDOUT;
+ }
+ if (pdm_enable == ACP_PDM_ENABLE) {
+ pdm_enable = ACP_PDM_DISABLE;
+ acp62_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE);
+ }
+ acp62_writel(0x01, acp_base + ACP_WOV_PDM_FIFO_FLUSH);
+ return 0;
+}
+
+static void acp62_config_dma(struct pdm_stream_instance *rtd, int direction)
+{
+ u16 page_idx;
+ u32 low, high, val;
+ dma_addr_t addr;
+
+ addr = rtd->dma_addr;
+ val = PDM_PTE_OFFSET;
+
+ /* Group Enable */
+ acp62_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp62_base +
+ ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
+ acp62_writel(PAGE_SIZE_4K_ENABLE, rtd->acp62_base +
+ ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
+ for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
+ /* Load the low address of page int ACP SRAM through SRBM */
+ low = lower_32_bits(addr);
+ high = upper_32_bits(addr);
+
+ acp62_writel(low, rtd->acp62_base + ACP_SCRATCH_REG_0 + val);
+ high |= BIT(31);
+ acp62_writel(high, rtd->acp62_base + ACP_SCRATCH_REG_0 + val + 4);
+ val += 8;
+ addr += PAGE_SIZE;
+ }
+}
+
+static int acp62_pdm_dma_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime;
+ struct pdm_dev_data *adata;
+ struct pdm_stream_instance *pdm_data;
+ int ret;
+
+ runtime = substream->runtime;
+ adata = dev_get_drvdata(component->dev);
+ pdm_data = kzalloc(sizeof(*pdm_data), GFP_KERNEL);
+ if (!pdm_data)
+ return -EINVAL;
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ runtime->hw = acp62_pdm_hardware_capture;
+
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0) {
+ dev_err(component->dev, "set integer constraint failed\n");
+ kfree(pdm_data);
+ return ret;
+ }
+
+ acp62_enable_pdm_interrupts(adata->acp62_base);
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ adata->capture_stream = substream;
+
+ pdm_data->acp62_base = adata->acp62_base;
+ runtime->private_data = pdm_data;
+ return ret;
+}
+
+static int acp62_pdm_dma_hw_params(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct pdm_stream_instance *rtd;
+ size_t size, period_bytes;
+
+ rtd = substream->runtime->private_data;
+ if (!rtd)
+ return -EINVAL;
+ size = params_buffer_bytes(params);
+ period_bytes = params_period_bytes(params);
+ rtd->dma_addr = substream->runtime->dma_addr;
+ rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
+ acp62_config_dma(rtd, substream->stream);
+ acp62_init_pdm_ring_buffer(PDM_MEM_WINDOW_START, size,
+ period_bytes, rtd->acp62_base);
+ return 0;
+}
+
+static u64 acp62_pdm_get_byte_count(struct pdm_stream_instance *rtd,
+ int direction)
+{
+ union acp_pdm_dma_count byte_count;
+
+ byte_count.bcount.high =
+ acp62_readl(rtd->acp62_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
+ byte_count.bcount.low =
+ acp62_readl(rtd->acp62_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
+ return byte_count.bytescount;
+}
+
+static snd_pcm_uframes_t acp62_pdm_dma_pointer(struct snd_soc_component *comp,
+ struct snd_pcm_substream *stream)
+{
+ struct pdm_stream_instance *rtd;
+ u32 pos, buffersize;
+ u64 bytescount;
+
+ rtd = stream->runtime->private_data;
+ buffersize = frames_to_bytes(stream->runtime,
+ stream->runtime->buffer_size);
+ bytescount = acp62_pdm_get_byte_count(rtd, stream->stream);
+ if (bytescount > rtd->bytescount)
+ bytescount -= rtd->bytescount;
+ pos = do_div(bytescount, buffersize);
+ return bytes_to_frames(stream->runtime, pos);
+}
+
+static int acp62_pdm_dma_new(struct snd_soc_component *component,
+ struct snd_soc_pcm_runtime *rtd)
+{
+ struct device *parent = component->dev->parent;
+
+ snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+ parent, MIN_BUFFER, MAX_BUFFER);
+ return 0;
+}
+
+static int acp62_pdm_dma_close(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct pdm_dev_data *adata = dev_get_drvdata(component->dev);
+
+ acp62_disable_pdm_interrupts(adata->acp62_base);
+ adata->capture_stream = NULL;
+ return 0;
+}
+
+static int acp62_pdm_dai_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct pdm_stream_instance *rtd;
+ int ret;
+ bool pdm_status;
+ unsigned int ch_mask;
+
+ rtd = substream->runtime->private_data;
+ ret = 0;
+ switch (substream->runtime->channels) {
+ case TWO_CH:
+ ch_mask = 0x00;
+ break;
+ default:
+ return -EINVAL;
+ }
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ acp62_writel(ch_mask, rtd->acp62_base + ACP_WOV_PDM_NO_OF_CHANNELS);
+ acp62_writel(PDM_DECIMATION_FACTOR, rtd->acp62_base +
+ ACP_WOV_PDM_DECIMATION_FACTOR);
+ rtd->bytescount = acp62_pdm_get_byte_count(rtd, substream->stream);
+ pdm_status = acp62_check_pdm_dma_status(rtd->acp62_base);
+ if (!pdm_status)
+ ret = acp62_start_pdm_dma(rtd->acp62_base);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ pdm_status = acp62_check_pdm_dma_status(rtd->acp62_base);
+ if (pdm_status)
+ ret = acp62_stop_pdm_dma(rtd->acp62_base);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static const struct snd_soc_dai_ops acp62_pdm_dai_ops = {
+ .trigger = acp62_pdm_dai_trigger,
+};
+
static struct snd_soc_dai_driver acp62_pdm_dai_driver = {
.name = "acp_ps_pdm_dma.0",
.capture = {
@@ -27,10 +331,16 @@ static struct snd_soc_dai_driver acp62_pdm_dai_driver = {
.rate_min = 48000,
.rate_max = 48000,
},
+ .ops = &acp62_pdm_dai_ops,
};

static const struct snd_soc_component_driver acp62_pdm_component = {
.name = DRV_NAME,
+ .open = acp62_pdm_dma_open,
+ .close = acp62_pdm_dma_close,
+ .hw_params = acp62_pdm_dma_hw_params,
+ .pointer = acp62_pdm_dma_pointer,
+ .pcm_construct = acp62_pdm_dma_new,
};

static int acp62_pdm_audio_probe(struct platform_device *pdev)
--
2.25.1


2022-08-12 15:00:44

by Amadeusz Sławiński

[permalink] [raw]
Subject: Re: [PATCH 07/13] ASoC: amd: add acp6.2 pdm driver dma ops

On 8/12/2022 2:07 PM, Syed Saba kareem wrote:
> This patch adds PDM driver DMA operations for Pink Sardine Platform.
>
> Signed-off-by: Syed Saba Kareem <[email protected]>
> ---
> sound/soc/amd/ps/acp62.h | 41 +++++
> sound/soc/amd/ps/ps-pdm-dma.c | 310 ++++++++++++++++++++++++++++++++++
> 2 files changed, 351 insertions(+)
>
> diff --git a/sound/soc/amd/ps/acp62.h b/sound/soc/amd/ps/acp62.h
> index 563252834b09..525e8bd225a2 100644
> --- a/sound/soc/amd/ps/acp62.h
> +++ b/sound/soc/amd/ps/acp62.h
> @@ -27,6 +27,31 @@
> #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
> #define PDM_DMA_STAT 0x10
>
> +#define PDM_DMA_INTR_MASK 0x10000
> +#define ACP_ERROR_STAT 29
> +#define PDM_DECIMATION_FACTOR 2
> +#define ACP_PDM_CLK_FREQ_MASK 7
> +#define ACP_WOV_MISC_CTRL_MASK 0x10
> +#define ACP_PDM_ENABLE 1
> +#define ACP_PDM_DISABLE 0
> +#define ACP_PDM_DMA_EN_STATUS 2
> +#define TWO_CH 2
> +#define DELAY_US 5
> +#define ACP_COUNTER 20000
> +
> +#define ACP_SRAM_PTE_OFFSET 0x03800000
> +#define PAGE_SIZE_4K_ENABLE 2
> +#define PDM_PTE_OFFSET 0
> +#define PDM_MEM_WINDOW_START 0x4000000
> +
> +#define CAPTURE_MIN_NUM_PERIODS 4
> +#define CAPTURE_MAX_NUM_PERIODS 4
> +#define CAPTURE_MAX_PERIOD_SIZE 8192
> +#define CAPTURE_MIN_PERIOD_SIZE 4096
> +
> +#define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS)
> +#define MIN_BUFFER MAX_BUFFER
> +
> enum acp_config {
> ACP_CONFIG_0 = 0,
> ACP_CONFIG_1,
> @@ -46,6 +71,22 @@ enum acp_config {
> ACP_CONFIG_15,
> };
>
> +struct pdm_stream_instance {
> + u16 num_pages;
> + u16 channels;
> + dma_addr_t dma_addr;
> + u64 bytescount;
> + void __iomem *acp62_base;
> +};
> +
> +union acp_pdm_dma_count {
> + struct {
> + u32 low;
> + u32 high;
> + } bcount;

Fix indentation.
Also you can remove struct name, and access fields directly, so instead
of accessing somevariable.bcount.low, you would use somevariable.low, it
would probably be more readable.

> + u64 bytescount;
> +};
> +
> struct pdm_dev_data {
> u32 pdm_irq;
> void __iomem *acp62_base;
> diff --git a/sound/soc/amd/ps/ps-pdm-dma.c b/sound/soc/amd/ps/ps-pdm-dma.c
> index bca2ac3e81f5..a98a2015015d 100644

...

> +
> +static int acp62_pdm_dma_open(struct snd_soc_component *component,
> + struct snd_pcm_substream *substream)
> +{
> + struct snd_pcm_runtime *runtime;
> + struct pdm_dev_data *adata;
> + struct pdm_stream_instance *pdm_data;
> + int ret;
> +
> + runtime = substream->runtime;
> + adata = dev_get_drvdata(component->dev);
> + pdm_data = kzalloc(sizeof(*pdm_data), GFP_KERNEL);
> + if (!pdm_data)
> + return -EINVAL;
> +
> + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
> + runtime->hw = acp62_pdm_hardware_capture;
> +
> + ret = snd_pcm_hw_constraint_integer(runtime,
> + SNDRV_PCM_HW_PARAM_PERIODS);
> + if (ret < 0) {
> + dev_err(component->dev, "set integer constraint failed\n");
> + kfree(pdm_data);
> + return ret;
> + }
> +
> + acp62_enable_pdm_interrupts(adata->acp62_base);
> +
> + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
> + adata->capture_stream = substream;
> +
> + pdm_data->acp62_base = adata->acp62_base;
> + runtime->private_data = pdm_data;

Should probably kfree(runtime->private_data) in acp62_pdm_dma_close(),
otherwise won't there be a memory leak?

> + return ret;
> +}
> +

...

2022-08-16 09:56:57

by syed saba kareem

[permalink] [raw]
Subject: Re: [PATCH 07/13] ASoC: amd: add acp6.2 pdm driver dma ops


On 8/12/22 19:50, Amadeusz Sławiński wrote:
> [CAUTION: External Email]
>
> On 8/12/2022 2:07 PM, Syed Saba kareem wrote:
>> This patch adds PDM driver DMA operations for Pink Sardine Platform.
>>
>> Signed-off-by: Syed Saba Kareem <[email protected]>
>> ---
>>   sound/soc/amd/ps/acp62.h      |  41 +++++
>>   sound/soc/amd/ps/ps-pdm-dma.c | 310 ++++++++++++++++++++++++++++++++++
>>   2 files changed, 351 insertions(+)
>>
>> diff --git a/sound/soc/amd/ps/acp62.h b/sound/soc/amd/ps/acp62.h
>> index 563252834b09..525e8bd225a2 100644
>> --- a/sound/soc/amd/ps/acp62.h
>> +++ b/sound/soc/amd/ps/acp62.h
>> @@ -27,6 +27,31 @@
>>   #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
>>   #define PDM_DMA_STAT 0x10
>>
>> +#define PDM_DMA_INTR_MASK    0x10000
>> +#define ACP_ERROR_STAT       29
>> +#define PDM_DECIMATION_FACTOR        2
>> +#define ACP_PDM_CLK_FREQ_MASK        7
>> +#define ACP_WOV_MISC_CTRL_MASK       0x10
>> +#define ACP_PDM_ENABLE               1
>> +#define ACP_PDM_DISABLE              0
>> +#define ACP_PDM_DMA_EN_STATUS        2
>> +#define TWO_CH               2
>> +#define DELAY_US     5
>> +#define ACP_COUNTER  20000
>> +
>> +#define ACP_SRAM_PTE_OFFSET  0x03800000
>> +#define PAGE_SIZE_4K_ENABLE  2
>> +#define PDM_PTE_OFFSET               0
>> +#define PDM_MEM_WINDOW_START 0x4000000
>> +
>> +#define CAPTURE_MIN_NUM_PERIODS     4
>> +#define CAPTURE_MAX_NUM_PERIODS     4
>> +#define CAPTURE_MAX_PERIOD_SIZE     8192
>> +#define CAPTURE_MIN_PERIOD_SIZE     4096
>> +
>> +#define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS)
>> +#define MIN_BUFFER MAX_BUFFER
>> +
>>   enum acp_config {
>>       ACP_CONFIG_0 = 0,
>>       ACP_CONFIG_1,
>> @@ -46,6 +71,22 @@ enum acp_config {
>>       ACP_CONFIG_15,
>>   };
>>
>> +struct pdm_stream_instance {
>> +     u16 num_pages;
>> +     u16 channels;
>> +     dma_addr_t dma_addr;
>> +     u64 bytescount;
>> +     void __iomem *acp62_base;
>> +};
>> +
>> +union acp_pdm_dma_count {
>> +     struct {
>> +     u32 low;
>> +     u32 high;
>> +     } bcount;
>
> Fix indentation.
> Also you can remove struct name, and access fields directly, so instead
> of accessing somevariable.bcount.low, you would use somevariable.low, it
> would probably be more readable.
>
Okay Will fix it.
>> +     u64 bytescount;
>> +};
>> +
>>   struct pdm_dev_data {
>>       u32 pdm_irq;
>>       void __iomem *acp62_base;
>> diff --git a/sound/soc/amd/ps/ps-pdm-dma.c
>> b/sound/soc/amd/ps/ps-pdm-dma.c
>> index bca2ac3e81f5..a98a2015015d 100644
>
> ...
>
>> +
>> +static int acp62_pdm_dma_open(struct snd_soc_component *component,
>> +                           struct snd_pcm_substream *substream)
>> +{
>> +     struct snd_pcm_runtime *runtime;
>> +     struct pdm_dev_data *adata;
>> +     struct pdm_stream_instance *pdm_data;
>> +     int ret;
>> +
>> +     runtime = substream->runtime;
>> +     adata = dev_get_drvdata(component->dev);
>> +     pdm_data = kzalloc(sizeof(*pdm_data), GFP_KERNEL);
>> +     if (!pdm_data)
>> +             return -EINVAL;
>> +
>> +     if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
>> +             runtime->hw = acp62_pdm_hardware_capture;
>> +
>> +     ret = snd_pcm_hw_constraint_integer(runtime,
>> + SNDRV_PCM_HW_PARAM_PERIODS);
>> +     if (ret < 0) {
>> +             dev_err(component->dev, "set integer constraint
>> failed\n");
>> +             kfree(pdm_data);
>> +             return ret;
>> +     }
>> +
>> +     acp62_enable_pdm_interrupts(adata->acp62_base);
>> +
>> +     if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
>> +             adata->capture_stream = substream;
>> +
>> +     pdm_data->acp62_base = adata->acp62_base;
>> +     runtime->private_data = pdm_data;
>
> Should probably kfree(runtime->private_data) in acp62_pdm_dma_close(),
> otherwise won't there be a memory leak?
>
Will fix it.
>> +     return ret;
>> +}
>> +
>
> ...
>