Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license. When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2023 Advanced Micro Devices, Inc.
7//
8// Authors: V Sujith Kumar Reddy <Vsujithkumar.Reddy@amd.com>
9
10/*
11 * Probe interface for generic AMD audio ACP DSP block
12 */
13
14#include <linux/module.h>
15#include <sound/soc.h>
16#include "../sof-priv.h"
17#include "../sof-client-probes.h"
18#include "../sof-client.h"
19#include "../ops.h"
20#include "acp.h"
21#include "acp-dsp-offset.h"
22
23static int acp_probes_compr_startup(struct sof_client_dev *cdev,
24 struct snd_compr_stream *cstream,
25 struct snd_soc_dai *dai, u32 *stream_id)
26{
27 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
28 struct acp_dsp_stream *stream;
29 struct acp_dev_data *adata;
30
31 adata = sdev->pdata->hw_pdata;
32 stream = acp_dsp_stream_get(sdev, 0);
33 if (!stream)
34 return -ENODEV;
35
36 stream->cstream = cstream;
37 cstream->runtime->private_data = stream;
38
39 adata->probe_stream = stream;
40 *stream_id = stream->stream_tag;
41
42 return 0;
43}
44
45static int acp_probes_compr_shutdown(struct sof_client_dev *cdev,
46 struct snd_compr_stream *cstream,
47 struct snd_soc_dai *dai)
48{
49 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
50 struct acp_dsp_stream *stream = cstream->runtime->private_data;
51 struct acp_dev_data *adata;
52 int ret;
53
54 ret = acp_dsp_stream_put(sdev, stream);
55 if (ret < 0) {
56 dev_err(sdev->dev, "Failed to release probe compress stream\n");
57 return ret;
58 }
59
60 adata = sdev->pdata->hw_pdata;
61 stream->cstream = NULL;
62 cstream->runtime->private_data = NULL;
63 adata->probe_stream = NULL;
64
65 return 0;
66}
67
68static int acp_probes_compr_set_params(struct sof_client_dev *cdev,
69 struct snd_compr_stream *cstream,
70 struct snd_compr_params *params,
71 struct snd_soc_dai *dai)
72{
73 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
74 struct acp_dsp_stream *stream = cstream->runtime->private_data;
75 unsigned int buf_offset, index;
76 u32 size;
77 int ret;
78
79 stream->dmab = cstream->runtime->dma_buffer_p;
80 stream->num_pages = PFN_UP(cstream->runtime->dma_bytes);
81 size = cstream->runtime->buffer_size;
82
83 ret = acp_dsp_stream_config(sdev, stream);
84 if (ret < 0) {
85 acp_dsp_stream_put(sdev, stream);
86 return ret;
87 }
88
89 /* write buffer size of stream in scratch memory */
90
91 buf_offset = sdev->debug_box.offset +
92 offsetof(struct scratch_reg_conf, buf_size);
93 index = stream->stream_tag - 1;
94 buf_offset = buf_offset + index * 4;
95
96 snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + buf_offset, size);
97
98 return 0;
99}
100
101static int acp_probes_compr_trigger(struct sof_client_dev *cdev,
102 struct snd_compr_stream *cstream,
103 int cmd, struct snd_soc_dai *dai)
104{
105 /* Nothing to do here, as it is a mandatory callback just defined */
106 return 0;
107}
108
109static int acp_probes_compr_pointer(struct sof_client_dev *cdev,
110 struct snd_compr_stream *cstream,
111 struct snd_compr_tstamp64 *tstamp,
112 struct snd_soc_dai *dai)
113{
114 struct acp_dsp_stream *stream = cstream->runtime->private_data;
115 struct snd_soc_pcm_stream *pstream;
116
117 pstream = &dai->driver->capture;
118 tstamp->copied_total = stream->cstream_posn;
119 tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates);
120
121 return 0;
122}
123
124/* SOF client implementation */
125static const struct sof_probes_host_ops acp_probes_ops = {
126 .startup = acp_probes_compr_startup,
127 .shutdown = acp_probes_compr_shutdown,
128 .set_params = acp_probes_compr_set_params,
129 .trigger = acp_probes_compr_trigger,
130 .pointer = acp_probes_compr_pointer,
131};
132
133int acp_probes_register(struct snd_sof_dev *sdev)
134{
135 return sof_client_dev_register(sdev, "acp-probes", 0, &acp_probes_ops,
136 sizeof(acp_probes_ops));
137}
138EXPORT_SYMBOL_NS(acp_probes_register, "SND_SOC_SOF_AMD_COMMON");
139
140void acp_probes_unregister(struct snd_sof_dev *sdev)
141{
142 sof_client_dev_unregister(sdev, "acp-probes", 0);
143}
144EXPORT_SYMBOL_NS(acp_probes_unregister, "SND_SOC_SOF_AMD_COMMON");
145
146MODULE_IMPORT_NS("SND_SOC_SOF_CLIENT");
147