xref: /linux/sound/soc/sof/amd/acp-probes.c (revision d27bb0246e5356dbef4d923e72c680bf893885a8)
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 
23 static 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 
45 static 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 
68 static 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 
101 static 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 
109 static int acp_probes_compr_pointer(struct sof_client_dev *cdev,
110 				    struct snd_compr_stream *cstream,
111 				    struct snd_compr_tstamp *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 */
125 static 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 
133 int 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 }
138 EXPORT_SYMBOL_NS(acp_probes_register, SND_SOC_SOF_AMD_COMMON);
139 
140 void acp_probes_unregister(struct snd_sof_dev *sdev)
141 {
142 	sof_client_dev_unregister(sdev, "acp-probes", 0);
143 }
144 EXPORT_SYMBOL_NS(acp_probes_unregister, SND_SOC_SOF_AMD_COMMON);
145 
146 MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
147 
148