162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// This file is provided under a dual BSD/GPLv2 license. When using or 462306a36Sopenharmony_ci// redistributing this file, you may do so under either license. 562306a36Sopenharmony_ci// 662306a36Sopenharmony_ci// Copyright(c) 2021 Advanced Micro Devices, Inc. 762306a36Sopenharmony_ci// 862306a36Sopenharmony_ci// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * PCM interface for generic AMD audio ACP DSP block 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#include <sound/pcm_params.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "../ops.h" 1662306a36Sopenharmony_ci#include "acp.h" 1762306a36Sopenharmony_ci#include "acp-dsp-offset.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciint acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, 2062306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 2162306a36Sopenharmony_ci struct snd_sof_platform_stream_params *platform_params) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 2462306a36Sopenharmony_ci struct acp_dsp_stream *stream = runtime->private_data; 2562306a36Sopenharmony_ci unsigned int buf_offset, index; 2662306a36Sopenharmony_ci u32 size; 2762306a36Sopenharmony_ci int ret; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci size = runtime->dma_bytes; 3062306a36Sopenharmony_ci stream->num_pages = PFN_UP(runtime->dma_bytes); 3162306a36Sopenharmony_ci stream->dmab = substream->runtime->dma_buffer_p; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci ret = acp_dsp_stream_config(sdev, stream); 3462306a36Sopenharmony_ci if (ret < 0) { 3562306a36Sopenharmony_ci dev_err(sdev->dev, "stream configuration failed\n"); 3662306a36Sopenharmony_ci return ret; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci platform_params->use_phy_address = true; 4062306a36Sopenharmony_ci platform_params->phy_addr = stream->reg_offset; 4162306a36Sopenharmony_ci platform_params->stream_tag = stream->stream_tag; 4262306a36Sopenharmony_ci platform_params->cont_update_posn = 1; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* write buffer size of stream in scratch memory */ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci buf_offset = sdev->debug_box.offset + 4762306a36Sopenharmony_ci offsetof(struct scratch_reg_conf, buf_size); 4862306a36Sopenharmony_ci index = stream->stream_tag - 1; 4962306a36Sopenharmony_ci buf_offset = buf_offset + index * 4; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + buf_offset, size); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci return 0; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ciEXPORT_SYMBOL_NS(acp_pcm_hw_params, SND_SOC_SOF_AMD_COMMON); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciint acp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct acp_dsp_stream *stream; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci stream = acp_dsp_stream_get(sdev, 0); 6262306a36Sopenharmony_ci if (!stream) 6362306a36Sopenharmony_ci return -ENODEV; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci substream->runtime->private_data = stream; 6662306a36Sopenharmony_ci stream->substream = substream; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci return 0; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ciEXPORT_SYMBOL_NS(acp_pcm_open, SND_SOC_SOF_AMD_COMMON); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ciint acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct acp_dsp_stream *stream; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci stream = substream->runtime->private_data; 7762306a36Sopenharmony_ci if (!stream) { 7862306a36Sopenharmony_ci dev_err(sdev->dev, "No open stream\n"); 7962306a36Sopenharmony_ci return -EINVAL; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci stream->substream = NULL; 8362306a36Sopenharmony_ci substream->runtime->private_data = NULL; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci return acp_dsp_stream_put(sdev, stream); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ciEXPORT_SYMBOL_NS(acp_pcm_close, SND_SOC_SOF_AMD_COMMON); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cisnd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev, 9062306a36Sopenharmony_ci struct snd_pcm_substream *substream) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 9362306a36Sopenharmony_ci struct snd_soc_component *scomp = sdev->component; 9462306a36Sopenharmony_ci struct snd_sof_pcm_stream *stream; 9562306a36Sopenharmony_ci struct sof_ipc_stream_posn posn; 9662306a36Sopenharmony_ci struct snd_sof_pcm *spcm; 9762306a36Sopenharmony_ci snd_pcm_uframes_t pos; 9862306a36Sopenharmony_ci int ret; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci spcm = snd_sof_find_spcm_dai(scomp, rtd); 10162306a36Sopenharmony_ci if (!spcm) { 10262306a36Sopenharmony_ci dev_warn_ratelimited(sdev->dev, "warn: can't find PCM with DAI ID %d\n", 10362306a36Sopenharmony_ci rtd->dai_link->id); 10462306a36Sopenharmony_ci return 0; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci stream = &spcm->stream[substream->stream]; 10862306a36Sopenharmony_ci ret = snd_sof_ipc_msg_data(sdev, stream, &posn, sizeof(posn)); 10962306a36Sopenharmony_ci if (ret < 0) { 11062306a36Sopenharmony_ci dev_warn(sdev->dev, "failed to read stream position: %d\n", ret); 11162306a36Sopenharmony_ci return 0; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci memcpy(&stream->posn, &posn, sizeof(posn)); 11562306a36Sopenharmony_ci pos = spcm->stream[substream->stream].posn.host_posn; 11662306a36Sopenharmony_ci pos = bytes_to_frames(substream->runtime, pos); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci return pos; 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ciEXPORT_SYMBOL_NS(acp_pcm_pointer, SND_SOC_SOF_AMD_COMMON); 121