mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	soundwire: stream: add helper to startup/shutdown streams
To handle streams at the dailink level, expose two helpers that will be called from machine drivers. Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> Link: https://lore.kernel.org/r/20200630184356.24939-3-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
		
							parent
							
								
									09553140c8
								
							
						
					
					
						commit
						4550569bd7
					
				
					 3 changed files with 110 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -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,7 +513,12 @@ In .shutdown() the data structure maintaining stream state are freed up.
 | 
			
		|||
 | 
			
		||||
  void sdw_release_stream(struct sdw_stream_runtime * stream);
 | 
			
		||||
 | 
			
		||||
Not Supported
 | 
			
		||||
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
 | 
			
		||||
=============
 | 
			
		||||
 | 
			
		||||
1. A single port with multiple channels supported cannot be used between two
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue