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
|
@ -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 @@ state_err:
|
|||
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 New Issue