Commit 4550569b authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Vinod Koul
Browse files

soundwire: stream: add helper to startup/shutdown streams

parent 09553140
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -293,6 +293,10 @@ per stream. From ASoC DPCM framework, this stream state maybe linked to

  int sdw_alloc_stream(char * stream_name);

The SoundWire core provides a sdw_startup_stream() helper function,
typically called during a dailink .startup() callback, which performs
stream allocation and sets the stream pointer for all DAIs
connected to a stream.

SDW_STREAM_CONFIGURED
~~~~~~~~~~~~~~~~~~~~~
@@ -509,6 +513,11 @@ In .shutdown() the data structure maintaining stream state are freed up.

  void sdw_release_stream(struct sdw_stream_runtime * stream);

The SoundWire core provides a sdw_shutdown_stream() helper function,
typically called during a dailink .shutdown() callback, which clears
the stream pointer for all DAIS connected to a stream and releases the
memory allocated for the stream.

  Not Supported
=============

+98 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/soundwire/sdw_registers.h>
#include <linux/soundwire/sdw.h>
#include <sound/soc.h>
#include "bus.h"

/*
@@ -1826,3 +1827,100 @@ int sdw_deprepare_stream(struct sdw_stream_runtime *stream)
	return ret;
}
EXPORT_SYMBOL(sdw_deprepare_stream);

static int set_stream(struct snd_pcm_substream *substream,
		      struct sdw_stream_runtime *sdw_stream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *dai;
	int ret = 0;
	int i;

	/* Set stream pointer on all DAIs */
	for_each_rtd_dais(rtd, i, dai) {
		ret = snd_soc_dai_set_sdw_stream(dai, sdw_stream, substream->stream);
		if (ret < 0) {
			dev_err(rtd->dev, "failed to set stream pointer on dai %s", dai->name);
			break;
		}
	}

	return ret;
}

/**
 * sdw_startup_stream() - Startup SoundWire stream
 *
 * @stream: Soundwire stream
 *
 * Documentation/driver-api/soundwire/stream.rst explains this API in detail
 */
int sdw_startup_stream(void *sdw_substream)
{
	struct snd_pcm_substream *substream = sdw_substream;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct sdw_stream_runtime *sdw_stream;
	char *name;
	int ret;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		name = kasprintf(GFP_KERNEL, "%s-Playback", substream->name);
	else
		name = kasprintf(GFP_KERNEL, "%s-Capture", substream->name);

	if (!name)
		return -ENOMEM;

	sdw_stream = sdw_alloc_stream(name);
	if (!sdw_stream) {
		dev_err(rtd->dev, "alloc stream failed for substream DAI %s", substream->name);
		ret = -ENOMEM;
		goto error;
	}

	ret = set_stream(substream, sdw_stream);
	if (ret < 0)
		goto release_stream;
	return 0;

release_stream:
	sdw_release_stream(sdw_stream);
	set_stream(substream, NULL);
error:
	kfree(name);
	return ret;
}
EXPORT_SYMBOL(sdw_startup_stream);

/**
 * sdw_shutdown_stream() - Shutdown SoundWire stream
 *
 * @stream: Soundwire stream
 *
 * Documentation/driver-api/soundwire/stream.rst explains this API in detail
 */
void sdw_shutdown_stream(void *sdw_substream)
{
	struct snd_pcm_substream *substream = sdw_substream;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct sdw_stream_runtime *sdw_stream;
	struct snd_soc_dai *dai;

	/* Find stream from first CPU DAI */
	dai = asoc_rtd_to_cpu(rtd, 0);

	sdw_stream = snd_soc_dai_get_sdw_stream(dai, substream->stream);

	if (!sdw_stream) {
		dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
		return;
	}

	/* release memory */
	kfree(sdw_stream->name);
	sdw_release_stream(sdw_stream);

	/* clear DAI data */
	set_stream(substream, NULL);
}
EXPORT_SYMBOL(sdw_shutdown_stream);
+2 −0
Original line number Diff line number Diff line
@@ -955,10 +955,12 @@ int sdw_stream_remove_master(struct sdw_bus *bus,
		struct sdw_stream_runtime *stream);
int sdw_stream_remove_slave(struct sdw_slave *slave,
		struct sdw_stream_runtime *stream);
int sdw_startup_stream(void *sdw_substream);
int sdw_prepare_stream(struct sdw_stream_runtime *stream);
int sdw_enable_stream(struct sdw_stream_runtime *stream);
int sdw_disable_stream(struct sdw_stream_runtime *stream);
int sdw_deprepare_stream(struct sdw_stream_runtime *stream);
void sdw_shutdown_stream(void *sdw_substream);
int sdw_bus_prep_clk_stop(struct sdw_bus *bus);
int sdw_bus_clk_stop(struct sdw_bus *bus);
int sdw_bus_exit_clk_stop(struct sdw_bus *bus);