// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018, Linaro Limited.
+// Copyright (c) 2018-2023, Linaro Limited.
 // Copyright (c) 2018, The Linux Foundation. All rights reserved.
 
 #include <dt-bindings/sound/qcom,q6afe.h>
 #include <sound/soc.h>
 #include "sdw.h"
 
+/**
+ * qcom_snd_sdw_startup() - Helper to start Soundwire stream for SoC audio card
+ * @substream: The PCM substream from audio, as passed to snd_soc_ops->startup()
+ *
+ * Helper for the SoC audio card (snd_soc_ops->startup()) to allocate and set
+ * Soundwire stream runtime to each codec DAI.
+ *
+ * The shutdown() callback should call sdw_release_stream() on the same
+ * sdw_stream_runtime.
+ *
+ * Return: 0 or errno
+ */
+int qcom_snd_sdw_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+       struct sdw_stream_runtime *sruntime;
+       struct snd_soc_dai *codec_dai;
+       int ret, i;
+
+       sruntime = sdw_alloc_stream(cpu_dai->name);
+       if (!sruntime)
+               return -ENOMEM;
+
+       for_each_rtd_codec_dais(rtd, i, codec_dai) {
+               ret = snd_soc_dai_set_stream(codec_dai, sruntime,
+                                            substream->stream);
+               if (ret < 0 && ret != -ENOTSUPP) {
+                       dev_err(rtd->dev, "Failed to set sdw stream on %s\n",
+                               codec_dai->name);
+                       goto err_set_stream;
+               }
+       }
+
+       return 0;
+
+err_set_stream:
+       sdw_release_stream(sruntime);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(qcom_snd_sdw_startup);
+
 int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
                         struct sdw_stream_runtime *sruntime,
                         bool *stream_prepared)