xref: /openbmc/linux/sound/soc/sof/intel/hda-probes.c (revision bdcf7926)
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 //
63dc0d709SPeter Ujfalusi // Copyright(c) 2019-2021 Intel Corporation. All rights reserved.
7f95b4152SPeter Ujfalusi //
8f95b4152SPeter Ujfalusi // Author: Cezary Rojewski <cezary.rojewski@intel.com>
93dc0d709SPeter Ujfalusi // Converted to SOF client:
103dc0d709SPeter Ujfalusi //  Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
113dc0d709SPeter Ujfalusi //  Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
12f95b4152SPeter Ujfalusi //
13f95b4152SPeter Ujfalusi 
143dc0d709SPeter Ujfalusi #include <linux/module.h>
15f95b4152SPeter Ujfalusi #include <sound/hdaudio_ext.h>
16f95b4152SPeter Ujfalusi #include <sound/soc.h>
17f95b4152SPeter Ujfalusi #include "../sof-priv.h"
183dc0d709SPeter Ujfalusi #include "../sof-client-probes.h"
193dc0d709SPeter Ujfalusi #include "../sof-client.h"
20f95b4152SPeter Ujfalusi #include "hda.h"
21f95b4152SPeter Ujfalusi 
22f95b4152SPeter Ujfalusi static inline struct hdac_ext_stream *
hda_compr_get_stream(struct snd_compr_stream * cstream)23f95b4152SPeter Ujfalusi hda_compr_get_stream(struct snd_compr_stream *cstream)
24f95b4152SPeter Ujfalusi {
25f95b4152SPeter Ujfalusi 	return cstream->runtime->private_data;
26f95b4152SPeter Ujfalusi }
27f95b4152SPeter Ujfalusi 
hda_probes_compr_startup(struct sof_client_dev * cdev,struct snd_compr_stream * cstream,struct snd_soc_dai * dai,u32 * stream_id)28*bdcf7926SPierre-Louis Bossart static int hda_probes_compr_startup(struct sof_client_dev *cdev,
29f95b4152SPeter Ujfalusi 				    struct snd_compr_stream *cstream,
303dc0d709SPeter Ujfalusi 				    struct snd_soc_dai *dai, u32 *stream_id)
31f95b4152SPeter Ujfalusi {
323dc0d709SPeter 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 
433dc0d709SPeter Ujfalusi 	*stream_id = hdac_stream(hext_stream)->stream_tag;
443dc0d709SPeter Ujfalusi 
453dc0d709SPeter Ujfalusi 	return 0;
46f95b4152SPeter Ujfalusi }
47f95b4152SPeter Ujfalusi 
hda_probes_compr_shutdown(struct sof_client_dev * cdev,struct snd_compr_stream * cstream,struct snd_soc_dai * dai)48*bdcf7926SPierre-Louis Bossart static int hda_probes_compr_shutdown(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);
533dc0d709SPeter 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 
hda_probes_compr_set_params(struct sof_client_dev * cdev,struct snd_compr_stream * cstream,struct snd_compr_params * params,struct snd_soc_dai * dai)693dc0d709SPeter 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);
753dc0d709SPeter 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 
hda_probes_compr_trigger(struct sof_client_dev * cdev,struct snd_compr_stream * cstream,int cmd,struct snd_soc_dai * dai)1033dc0d709SPeter Ujfalusi static int hda_probes_compr_trigger(struct sof_client_dev *cdev,
1043dc0d709SPeter Ujfalusi 				    struct snd_compr_stream *cstream,
1053dc0d709SPeter Ujfalusi 				    int cmd, struct snd_soc_dai *dai)
106f95b4152SPeter Ujfalusi {
1077d88b960SPierre-Louis Bossart 	struct hdac_ext_stream *hext_stream = hda_compr_get_stream(cstream);
1083dc0d709SPeter 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 
hda_probes_compr_pointer(struct sof_client_dev * cdev,struct snd_compr_stream * cstream,struct snd_compr_tstamp * tstamp,struct snd_soc_dai * dai)1133dc0d709SPeter 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 }
1273dc0d709SPeter Ujfalusi 
1283dc0d709SPeter Ujfalusi /* SOF client implementation */
1293dc0d709SPeter Ujfalusi static const struct sof_probes_host_ops hda_probes_ops = {
130*bdcf7926SPierre-Louis Bossart 	.startup = hda_probes_compr_startup,
131*bdcf7926SPierre-Louis Bossart 	.shutdown = hda_probes_compr_shutdown,
1323dc0d709SPeter Ujfalusi 	.set_params = hda_probes_compr_set_params,
1333dc0d709SPeter Ujfalusi 	.trigger = hda_probes_compr_trigger,
1343dc0d709SPeter Ujfalusi 	.pointer = hda_probes_compr_pointer,
1353dc0d709SPeter Ujfalusi };
1363dc0d709SPeter Ujfalusi 
hda_probes_register(struct snd_sof_dev * sdev)1373dc0d709SPeter Ujfalusi int hda_probes_register(struct snd_sof_dev *sdev)
1383dc0d709SPeter Ujfalusi {
1393dc0d709SPeter Ujfalusi 	return sof_client_dev_register(sdev, "hda-probes", 0, &hda_probes_ops,
1403dc0d709SPeter Ujfalusi 				       sizeof(hda_probes_ops));
1413dc0d709SPeter Ujfalusi }
1423dc0d709SPeter Ujfalusi 
hda_probes_unregister(struct snd_sof_dev * sdev)1433dc0d709SPeter Ujfalusi void hda_probes_unregister(struct snd_sof_dev *sdev)
1443dc0d709SPeter Ujfalusi {
1453dc0d709SPeter Ujfalusi 	sof_client_dev_unregister(sdev, "hda-probes", 0);
1463dc0d709SPeter Ujfalusi }
1473dc0d709SPeter Ujfalusi 
1483dc0d709SPeter Ujfalusi MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
149