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) 2023 Advanced Micro Devices, Inc. 762306a36Sopenharmony_ci// 862306a36Sopenharmony_ci// Authors: V Sujith Kumar Reddy <Vsujithkumar.Reddy@amd.com> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * Probe interface for generic AMD audio ACP DSP block 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <sound/soc.h> 1662306a36Sopenharmony_ci#include "../sof-priv.h" 1762306a36Sopenharmony_ci#include "../sof-client-probes.h" 1862306a36Sopenharmony_ci#include "../sof-client.h" 1962306a36Sopenharmony_ci#include "../ops.h" 2062306a36Sopenharmony_ci#include "acp.h" 2162306a36Sopenharmony_ci#include "acp-dsp-offset.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int acp_probes_compr_startup(struct sof_client_dev *cdev, 2462306a36Sopenharmony_ci struct snd_compr_stream *cstream, 2562306a36Sopenharmony_ci struct snd_soc_dai *dai, u32 *stream_id) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 2862306a36Sopenharmony_ci struct acp_dsp_stream *stream; 2962306a36Sopenharmony_ci struct acp_dev_data *adata; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci adata = sdev->pdata->hw_pdata; 3262306a36Sopenharmony_ci stream = acp_dsp_stream_get(sdev, 0); 3362306a36Sopenharmony_ci if (!stream) 3462306a36Sopenharmony_ci return -ENODEV; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci stream->cstream = cstream; 3762306a36Sopenharmony_ci cstream->runtime->private_data = stream; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci adata->probe_stream = stream; 4062306a36Sopenharmony_ci *stream_id = stream->stream_tag; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci return 0; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic int acp_probes_compr_shutdown(struct sof_client_dev *cdev, 4662306a36Sopenharmony_ci struct snd_compr_stream *cstream, 4762306a36Sopenharmony_ci struct snd_soc_dai *dai) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 5062306a36Sopenharmony_ci struct acp_dsp_stream *stream = cstream->runtime->private_data; 5162306a36Sopenharmony_ci struct acp_dev_data *adata; 5262306a36Sopenharmony_ci int ret; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci ret = acp_dsp_stream_put(sdev, stream); 5562306a36Sopenharmony_ci if (ret < 0) { 5662306a36Sopenharmony_ci dev_err(sdev->dev, "Failed to release probe compress stream\n"); 5762306a36Sopenharmony_ci return ret; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci adata = sdev->pdata->hw_pdata; 6162306a36Sopenharmony_ci stream->cstream = NULL; 6262306a36Sopenharmony_ci cstream->runtime->private_data = NULL; 6362306a36Sopenharmony_ci adata->probe_stream = NULL; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic int acp_probes_compr_set_params(struct sof_client_dev *cdev, 6962306a36Sopenharmony_ci struct snd_compr_stream *cstream, 7062306a36Sopenharmony_ci struct snd_compr_params *params, 7162306a36Sopenharmony_ci struct snd_soc_dai *dai) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 7462306a36Sopenharmony_ci struct acp_dsp_stream *stream = cstream->runtime->private_data; 7562306a36Sopenharmony_ci unsigned int buf_offset, index; 7662306a36Sopenharmony_ci u32 size; 7762306a36Sopenharmony_ci int ret; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci stream->dmab = cstream->runtime->dma_buffer_p; 8062306a36Sopenharmony_ci stream->num_pages = PFN_UP(cstream->runtime->dma_bytes); 8162306a36Sopenharmony_ci size = cstream->runtime->buffer_size; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci ret = acp_dsp_stream_config(sdev, stream); 8462306a36Sopenharmony_ci if (ret < 0) { 8562306a36Sopenharmony_ci acp_dsp_stream_put(sdev, stream); 8662306a36Sopenharmony_ci return ret; 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* write buffer size of stream in scratch memory */ 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci buf_offset = sdev->debug_box.offset + 9262306a36Sopenharmony_ci offsetof(struct scratch_reg_conf, buf_size); 9362306a36Sopenharmony_ci index = stream->stream_tag - 1; 9462306a36Sopenharmony_ci buf_offset = buf_offset + index * 4; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + buf_offset, size); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci return 0; 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic int acp_probes_compr_trigger(struct sof_client_dev *cdev, 10262306a36Sopenharmony_ci struct snd_compr_stream *cstream, 10362306a36Sopenharmony_ci int cmd, struct snd_soc_dai *dai) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci /* Nothing to do here, as it is a mandatory callback just defined */ 10662306a36Sopenharmony_ci return 0; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int acp_probes_compr_pointer(struct sof_client_dev *cdev, 11062306a36Sopenharmony_ci struct snd_compr_stream *cstream, 11162306a36Sopenharmony_ci struct snd_compr_tstamp *tstamp, 11262306a36Sopenharmony_ci struct snd_soc_dai *dai) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct acp_dsp_stream *stream = cstream->runtime->private_data; 11562306a36Sopenharmony_ci struct snd_soc_pcm_stream *pstream; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci pstream = &dai->driver->capture; 11862306a36Sopenharmony_ci tstamp->copied_total = stream->cstream_posn; 11962306a36Sopenharmony_ci tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* SOF client implementation */ 12562306a36Sopenharmony_cistatic const struct sof_probes_host_ops acp_probes_ops = { 12662306a36Sopenharmony_ci .startup = acp_probes_compr_startup, 12762306a36Sopenharmony_ci .shutdown = acp_probes_compr_shutdown, 12862306a36Sopenharmony_ci .set_params = acp_probes_compr_set_params, 12962306a36Sopenharmony_ci .trigger = acp_probes_compr_trigger, 13062306a36Sopenharmony_ci .pointer = acp_probes_compr_pointer, 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciint acp_probes_register(struct snd_sof_dev *sdev) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci return sof_client_dev_register(sdev, "acp-probes", 0, &acp_probes_ops, 13662306a36Sopenharmony_ci sizeof(acp_probes_ops)); 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ciEXPORT_SYMBOL_NS(acp_probes_register, SND_SOC_SOF_AMD_COMMON); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_civoid acp_probes_unregister(struct snd_sof_dev *sdev) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci sof_client_dev_unregister(sdev, "acp-probes", 0); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ciEXPORT_SYMBOL_NS(acp_probes_unregister, SND_SOC_SOF_AMD_COMMON); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciMODULE_IMPORT_NS(SND_SOC_SOF_CLIENT); 14762306a36Sopenharmony_ci 148