xref: /openbmc/linux/sound/soc/sof/intel/hda-probes.c (revision 3dc0d709177828a22dfc9d0072e3ac937ef90d06)
1f95b4152SPeter Ujfalusi // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2f95b4152SPeter Ujfalusi //
3f95b4152SPeter Ujfalusi // This file is provided under a dual BSD/GPLv2 license.  When using or
4f95b4152SPeter Ujfalusi // redistributing this file, you may do so under either license.
5f95b4152SPeter Ujfalusi //
6*3dc0d709SPeter Ujfalusi // Copyright(c) 2019-2021 Intel Corporation. All rights reserved.
7f95b4152SPeter Ujfalusi //
8f95b4152SPeter Ujfalusi // Author: Cezary Rojewski <cezary.rojewski@intel.com>
9*3dc0d709SPeter Ujfalusi // Converted to SOF client:
10*3dc0d709SPeter Ujfalusi //  Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
11*3dc0d709SPeter Ujfalusi //  Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
12f95b4152SPeter Ujfalusi //
13f95b4152SPeter Ujfalusi 
14*3dc0d709SPeter Ujfalusi #include <linux/module.h>
15f95b4152SPeter Ujfalusi #include <sound/hdaudio_ext.h>
16f95b4152SPeter Ujfalusi #include <sound/soc.h>
17f95b4152SPeter Ujfalusi #include "../sof-priv.h"
18*3dc0d709SPeter Ujfalusi #include "../sof-client-probes.h"
19*3dc0d709SPeter Ujfalusi #include "../sof-client.h"
20f95b4152SPeter Ujfalusi #include "hda.h"
21f95b4152SPeter Ujfalusi 
22f95b4152SPeter Ujfalusi static inline struct hdac_ext_stream *
23f95b4152SPeter Ujfalusi hda_compr_get_stream(struct snd_compr_stream *cstream)
24f95b4152SPeter Ujfalusi {
25f95b4152SPeter Ujfalusi 	return cstream->runtime->private_data;
26f95b4152SPeter Ujfalusi }
27f95b4152SPeter Ujfalusi 
28*3dc0d709SPeter Ujfalusi static int hda_probes_compr_assign(struct sof_client_dev *cdev,
29f95b4152SPeter Ujfalusi 				   struct snd_compr_stream *cstream,
30*3dc0d709SPeter Ujfalusi 				   struct snd_soc_dai *dai, u32 *stream_id)
31f95b4152SPeter Ujfalusi {
32*3dc0d709SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
337d88b960SPierre-Louis Bossart 	struct hdac_ext_stream *hext_stream;
34f95b4152SPeter Ujfalusi 
357d88b960SPierre-Louis Bossart 	hext_stream = hda_dsp_stream_get(sdev, cstream->direction, 0);
367d88b960SPierre-Louis Bossart 	if (!hext_stream)
37f95b4152SPeter Ujfalusi 		return -EBUSY;
38f95b4152SPeter Ujfalusi 
397d88b960SPierre-Louis Bossart 	hdac_stream(hext_stream)->curr_pos = 0;
407d88b960SPierre-Louis Bossart 	hdac_stream(hext_stream)->cstream = cstream;
417d88b960SPierre-Louis Bossart 	cstream->runtime->private_data = hext_stream;
42f95b4152SPeter Ujfalusi 
43*3dc0d709SPeter Ujfalusi 	*stream_id = hdac_stream(hext_stream)->stream_tag;
44*3dc0d709SPeter Ujfalusi 
45*3dc0d709SPeter Ujfalusi 	return 0;
46f95b4152SPeter Ujfalusi }
47f95b4152SPeter Ujfalusi 
48*3dc0d709SPeter Ujfalusi static int hda_probes_compr_free(struct sof_client_dev *cdev,
49f95b4152SPeter Ujfalusi 				 struct snd_compr_stream *cstream,
50f95b4152SPeter Ujfalusi 				 struct snd_soc_dai *dai)
51f95b4152SPeter Ujfalusi {
527d88b960SPierre-Louis Bossart 	struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
53*3dc0d709SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
54f95b4152SPeter Ujfalusi 	int ret;
55f95b4152SPeter Ujfalusi 
56f95b4152SPeter Ujfalusi 	ret = hda_dsp_stream_put(sdev, cstream->direction,
577d88b960SPierre-Louis Bossart 				 hdac_stream(hext_stream)->stream_tag);
58f95b4152SPeter Ujfalusi 	if (ret < 0) {
59f95b4152SPeter Ujfalusi 		dev_dbg(sdev->dev, "stream put failed: %d\n", ret);
60f95b4152SPeter Ujfalusi 		return ret;
61f95b4152SPeter Ujfalusi 	}
62f95b4152SPeter Ujfalusi 
637d88b960SPierre-Louis Bossart 	hdac_stream(hext_stream)->cstream = NULL;
64f95b4152SPeter Ujfalusi 	cstream->runtime->private_data = NULL;
65f95b4152SPeter Ujfalusi 
66f95b4152SPeter Ujfalusi 	return 0;
67f95b4152SPeter Ujfalusi }
68f95b4152SPeter Ujfalusi 
69*3dc0d709SPeter Ujfalusi static int hda_probes_compr_set_params(struct sof_client_dev *cdev,
70f95b4152SPeter Ujfalusi 				       struct snd_compr_stream *cstream,
71f95b4152SPeter Ujfalusi 				       struct snd_compr_params *params,
72f95b4152SPeter Ujfalusi 				       struct snd_soc_dai *dai)
73f95b4152SPeter Ujfalusi {
747d88b960SPierre-Louis Bossart 	struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
75*3dc0d709SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
767d88b960SPierre-Louis Bossart 	struct hdac_stream *hstream = hdac_stream(hext_stream);
77f95b4152SPeter Ujfalusi 	struct snd_dma_buffer *dmab;
78f95b4152SPeter Ujfalusi 	u32 bits, rate;
79f95b4152SPeter Ujfalusi 	int bps, ret;
80f95b4152SPeter Ujfalusi 
81f95b4152SPeter Ujfalusi 	dmab = cstream->runtime->dma_buffer_p;
82f95b4152SPeter Ujfalusi 	/* compr params do not store bit depth, default to S32_LE */
83f95b4152SPeter Ujfalusi 	bps = snd_pcm_format_physical_width(SNDRV_PCM_FORMAT_S32_LE);
84f95b4152SPeter Ujfalusi 	if (bps < 0)
85f95b4152SPeter Ujfalusi 		return bps;
86f95b4152SPeter Ujfalusi 	bits = hda_dsp_get_bits(sdev, bps);
87f95b4152SPeter Ujfalusi 	rate = hda_dsp_get_mult_div(sdev, params->codec.sample_rate);
88f95b4152SPeter Ujfalusi 
89f95b4152SPeter Ujfalusi 	hstream->format_val = rate | bits | (params->codec.ch_out - 1);
90f95b4152SPeter Ujfalusi 	hstream->bufsize = cstream->runtime->buffer_size;
91f95b4152SPeter Ujfalusi 	hstream->period_bytes = cstream->runtime->fragment_size;
92f95b4152SPeter Ujfalusi 	hstream->no_period_wakeup = 0;
93f95b4152SPeter Ujfalusi 
947d88b960SPierre-Louis Bossart 	ret = hda_dsp_stream_hw_params(sdev, hext_stream, dmab, NULL);
95f95b4152SPeter Ujfalusi 	if (ret < 0) {
96f95b4152SPeter Ujfalusi 		dev_err(sdev->dev, "error: hdac prepare failed: %d\n", ret);
97f95b4152SPeter Ujfalusi 		return ret;
98f95b4152SPeter Ujfalusi 	}
99f95b4152SPeter Ujfalusi 
100f95b4152SPeter Ujfalusi 	return 0;
101f95b4152SPeter Ujfalusi }
102f95b4152SPeter Ujfalusi 
103*3dc0d709SPeter Ujfalusi static int hda_probes_compr_trigger(struct sof_client_dev *cdev,
104*3dc0d709SPeter Ujfalusi 				    struct snd_compr_stream *cstream,
105*3dc0d709SPeter Ujfalusi 				    int cmd, struct snd_soc_dai *dai)
106f95b4152SPeter Ujfalusi {
1077d88b960SPierre-Louis Bossart 	struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
108*3dc0d709SPeter Ujfalusi 	struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev);
109f95b4152SPeter Ujfalusi 
1107d88b960SPierre-Louis Bossart 	return hda_dsp_stream_trigger(sdev, hext_stream, cmd);
111f95b4152SPeter Ujfalusi }
112f95b4152SPeter Ujfalusi 
113*3dc0d709SPeter Ujfalusi static int hda_probes_compr_pointer(struct sof_client_dev *cdev,
114f95b4152SPeter Ujfalusi 				    struct snd_compr_stream *cstream,
115f95b4152SPeter Ujfalusi 				    struct snd_compr_tstamp *tstamp,
116f95b4152SPeter Ujfalusi 				    struct snd_soc_dai *dai)
117f95b4152SPeter Ujfalusi {
1187d88b960SPierre-Louis Bossart 	struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
119f95b4152SPeter Ujfalusi 	struct snd_soc_pcm_stream *pstream;
120f95b4152SPeter Ujfalusi 
121f95b4152SPeter Ujfalusi 	pstream = &dai->driver->capture;
1227d88b960SPierre-Louis Bossart 	tstamp->copied_total = hdac_stream(hext_stream)->curr_pos;
123f95b4152SPeter Ujfalusi 	tstamp->sampling_rate = snd_pcm_rate_bit_to_rate(pstream->rates);
124f95b4152SPeter Ujfalusi 
125f95b4152SPeter Ujfalusi 	return 0;
126f95b4152SPeter Ujfalusi }
127*3dc0d709SPeter Ujfalusi 
128*3dc0d709SPeter Ujfalusi /* SOF client implementation */
129*3dc0d709SPeter Ujfalusi static const struct sof_probes_host_ops hda_probes_ops = {
130*3dc0d709SPeter Ujfalusi 	.assign = hda_probes_compr_assign,
131*3dc0d709SPeter Ujfalusi 	.free = hda_probes_compr_free,
132*3dc0d709SPeter Ujfalusi 	.set_params = hda_probes_compr_set_params,
133*3dc0d709SPeter Ujfalusi 	.trigger = hda_probes_compr_trigger,
134*3dc0d709SPeter Ujfalusi 	.pointer = hda_probes_compr_pointer,
135*3dc0d709SPeter Ujfalusi };
136*3dc0d709SPeter Ujfalusi 
137*3dc0d709SPeter Ujfalusi int hda_probes_register(struct snd_sof_dev *sdev)
138*3dc0d709SPeter Ujfalusi {
139*3dc0d709SPeter Ujfalusi 	return sof_client_dev_register(sdev, "hda-probes", 0, &hda_probes_ops,
140*3dc0d709SPeter Ujfalusi 				       sizeof(hda_probes_ops));
141*3dc0d709SPeter Ujfalusi }
142*3dc0d709SPeter Ujfalusi 
143*3dc0d709SPeter Ujfalusi void hda_probes_unregister(struct snd_sof_dev *sdev)
144*3dc0d709SPeter Ujfalusi {
145*3dc0d709SPeter Ujfalusi 	sof_client_dev_unregister(sdev, "hda-probes", 0);
146*3dc0d709SPeter Ujfalusi }
147*3dc0d709SPeter Ujfalusi 
148*3dc0d709SPeter Ujfalusi MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
149