| From d6c5925b4c467f5c45029f98145f00b16b0c1557 Mon Sep 17 00:00:00 2001 |
| From: V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com> |
| Date: Fri, 1 Jul 2022 12:43:29 +0530 |
| Subject: [PATCH] CHROMIUM: ASOC: SOF: amd : Implementation of sof host stream |
| pointer callback function |
| |
| This patch adds pointer callback implementation for acp pcm driver. |
| |
| BUG=b:236819380 |
| TEST=Tested on skyrim |
| |
| Change-Id: I97e52b608e7a9a39746733869d9bd0579faee7bb |
| Signed-off-by: V sujith kumar Reddy <vsujithkumar.reddy@amd.corp-partner.google.com> |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3735265 |
| Reviewed-by: Yu-Hsuan Hsu <yuhsuan@chromium.org> |
| Tested-by: Yu-Hsuan Hsu <yuhsuan@chromium.org> |
| Commit-Queue: Yu-Hsuan Hsu <yuhsuan@chromium.org> |
| --- |
| sound/soc/sof/amd/acp-common.c | 1 + |
| sound/soc/sof/amd/acp-dsp-offset.h | 18 ++++++ |
| sound/soc/sof/amd/acp-pcm.c | 95 ++++++++++++++++++++++++++++++ |
| sound/soc/sof/amd/acp.h | 14 +++++ |
| 4 files changed, 128 insertions(+) |
| |
| diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c |
| index bd6c1b198736c031b1454e49206653c6bd5603e6..8ce4c89569338d1b483c7ee18c73f55aed7d605b 100644 |
| --- a/sound/soc/sof/amd/acp-common.c |
| +++ b/sound/soc/sof/amd/acp-common.c |
| @@ -187,6 +187,7 @@ struct snd_sof_dsp_ops sof_acp_common_ops = { |
| .pcm_open = acp_pcm_open, |
| .pcm_close = acp_pcm_close, |
| .pcm_hw_params = acp_pcm_hw_params, |
| + .pcm_pointer = acp_pcm_pointer, |
| |
| .hw_info = SNDRV_PCM_INFO_MMAP | |
| SNDRV_PCM_INFO_MMAP_VALID | |
| diff --git a/sound/soc/sof/amd/acp-dsp-offset.h b/sound/soc/sof/amd/acp-dsp-offset.h |
| index 920155dee819b508c21116034ec3b45e8d56240e..f13ec6b5b14885e016b10d6e0f975e77d9d349f2 100644 |
| --- a/sound/soc/sof/amd/acp-dsp-offset.h |
| +++ b/sound/soc/sof/amd/acp-dsp-offset.h |
| @@ -89,4 +89,22 @@ |
| /* Cache window registers */ |
| #define ACP_DSP0_CACHE_OFFSET0 0x0420 |
| #define ACP_DSP0_CACHE_SIZE0 0x0424 |
| + |
| +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x2018 |
| +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x201C |
| +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x203C |
| +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x2040 |
| + |
| +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x2060 |
| +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x2064 |
| +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x2084 |
| +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x2088 |
| + |
| +#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x3AA8 |
| +#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x3AAC |
| +#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x3ACC |
| +#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x3AD0 |
| + |
| +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x2C18 |
| +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x2C1C |
| #endif |
| diff --git a/sound/soc/sof/amd/acp-pcm.c b/sound/soc/sof/amd/acp-pcm.c |
| index 727c3a784a204f105c185c704b23c7c95933c9a2..abedb037bb9c36ee40a078b0613c7006b3f14314 100644 |
| --- a/sound/soc/sof/amd/acp-pcm.c |
| +++ b/sound/soc/sof/amd/acp-pcm.c |
| @@ -15,6 +15,7 @@ |
| #include "../ops.h" |
| #include "acp.h" |
| #include "acp-dsp-offset.h" |
| +#include "../sof-audio.h" |
| |
| int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, |
| struct snd_pcm_hw_params *params, |
| @@ -84,3 +85,97 @@ int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) |
| return acp_dsp_stream_put(sdev, stream); |
| } |
| EXPORT_SYMBOL_NS(acp_pcm_close, SND_SOC_SOF_AMD_COMMON); |
| + |
| +static const struct acp_pcm_table pcm_dev[] = { |
| + {I2S_BT, "I2SBT"}, |
| + {I2S_SP, "I2SSP"}, |
| + {PDM_DMIC, "DMIC"}, |
| + {I2S_HS, "I2SHS"}, |
| +}; |
| + |
| +static enum acp_pcm_types get_id_from_list(const char *name) |
| +{ |
| + int i; |
| + |
| + for (i = 0; i < ARRAY_SIZE(pcm_dev); i++) { |
| + if (!strcmp(name, pcm_dev[i].pcm_name)) |
| + return pcm_dev[i].pcm_index; |
| + } |
| + |
| + return PCM_NONE; |
| +} |
| + |
| +static u64 acp_get_byte_count(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, |
| + enum acp_pcm_types pcm_id) |
| +{ |
| + u64 bytescount, low = 0, high = 0; |
| + u32 reg1 = 0, reg2 = 0; |
| + |
| + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| + switch (pcm_id) { |
| + case I2S_BT: |
| + reg1 = ACP_BT_TX_LINEARPOSITIONCNTR_HIGH; |
| + reg2 = ACP_BT_TX_LINEARPOSITIONCNTR_LOW; |
| + break; |
| + case I2S_SP: |
| + reg1 = ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH; |
| + reg2 = ACP_I2S_TX_LINEARPOSITIONCNTR_LOW; |
| + break; |
| + case I2S_HS: |
| + reg1 = ACP_HS_TX_LINEARPOSITIONCNTR_HIGH; |
| + reg2 = ACP_HS_TX_LINEARPOSITIONCNTR_LOW; |
| + break; |
| + default: |
| + return -EINVAL; |
| + } |
| + } else { |
| + switch (pcm_id) { |
| + case I2S_BT: |
| + reg1 = ACP_BT_RX_LINEARPOSITIONCNTR_HIGH; |
| + reg2 = ACP_BT_RX_LINEARPOSITIONCNTR_LOW; |
| + break; |
| + case I2S_SP: |
| + reg1 = ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH; |
| + reg2 = ACP_I2S_RX_LINEARPOSITIONCNTR_LOW; |
| + break; |
| + case I2S_HS: |
| + reg1 = ACP_HS_RX_LINEARPOSITIONCNTR_HIGH; |
| + reg2 = ACP_HS_RX_LINEARPOSITIONCNTR_LOW; |
| + break; |
| + case PDM_DMIC: |
| + reg1 = ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH; |
| + reg2 = ACP_WOV_RX_LINEARPOSITIONCNTR_LOW; |
| + break; |
| + default: |
| + return -EINVAL; |
| + } |
| + } |
| + |
| + high = snd_sof_dsp_read(sdev, ACP_DSP_BAR, reg1); |
| + low = snd_sof_dsp_read(sdev, ACP_DSP_BAR, reg2); |
| + |
| + bytescount = (high << 32) | low; |
| + return bytescount; |
| +} |
| + |
| +snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) |
| +{ |
| + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
| + struct snd_soc_component *scomp = sdev->component; |
| + enum acp_pcm_types pcm_id = PCM_NONE; |
| + struct snd_sof_pcm *spcm; |
| + u32 pos, buffersize; |
| + u64 bytescount; |
| + |
| + spcm = snd_sof_find_spcm_dai(scomp, rtd); |
| + pcm_id = get_id_from_list(spcm->pcm.pcm_name); |
| + |
| + bytescount = acp_get_byte_count(sdev, substream, pcm_id); |
| + if (bytescount < 0) |
| + return -EINVAL; |
| + buffersize = frames_to_bytes(substream->runtime, substream->runtime->buffer_size); |
| + pos = do_div(bytescount, buffersize); |
| + |
| + return bytes_to_frames(substream->runtime, pos); |
| +} |
| +EXPORT_SYMBOL_NS(acp_pcm_pointer, SND_SOC_SOF_AMD_COMMON); |
| diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h |
| index 39165ebf684b68e6f9a37a46b12d1b4e59dfd1c7..55d1975b5bb1e3b4ebced19de7fdcbcd44cb4c2e 100644 |
| --- a/sound/soc/sof/amd/acp.h |
| +++ b/sound/soc/sof/amd/acp.h |
| @@ -185,6 +185,19 @@ struct acp_dev_data { |
| struct pci_dev *smn_dev; |
| }; |
| |
| +enum acp_pcm_types { |
| + I2S_BT = 0, |
| + I2S_SP, |
| + PDM_DMIC, |
| + I2S_HS, |
| + PCM_NONE, |
| +}; |
| + |
| +struct acp_pcm_table { |
| + u8 pcm_index; |
| + char *pcm_name; |
| +}; |
| + |
| void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src, size_t bytes); |
| void memcpy_from_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *dst, size_t bytes); |
| |
| @@ -238,6 +251,7 @@ int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) |
| int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, |
| struct snd_pcm_hw_params *params, |
| struct snd_sof_platform_stream_params *platform_params); |
| +snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); |
| |
| extern struct snd_sof_dsp_ops sof_acp_common_ops; |
| |
| -- |
| 2.38.3 |
| |