~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/qcom/sdw.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 // Copyright (c) 2018-2023, Linaro Limited.
  3 // Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4 
  5 #include <dt-bindings/sound/qcom,q6afe.h>
  6 #include <linux/module.h>
  7 #include <sound/soc.h>
  8 #include "sdw.h"
  9 
 10 /**
 11  * qcom_snd_sdw_startup() - Helper to start Soundwire stream for SoC audio card
 12  * @substream: The PCM substream from audio, as passed to snd_soc_ops->startup()
 13  *
 14  * Helper for the SoC audio card (snd_soc_ops->startup()) to allocate and set
 15  * Soundwire stream runtime to each codec DAI.
 16  *
 17  * The shutdown() callback should call sdw_release_stream() on the same
 18  * sdw_stream_runtime.
 19  *
 20  * Return: 0 or errno
 21  */
 22 int qcom_snd_sdw_startup(struct snd_pcm_substream *substream)
 23 {
 24         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 25         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
 26         struct sdw_stream_runtime *sruntime;
 27         struct snd_soc_dai *codec_dai;
 28         int ret, i;
 29 
 30         sruntime = sdw_alloc_stream(cpu_dai->name);
 31         if (!sruntime)
 32                 return -ENOMEM;
 33 
 34         for_each_rtd_codec_dais(rtd, i, codec_dai) {
 35                 ret = snd_soc_dai_set_stream(codec_dai, sruntime,
 36                                              substream->stream);
 37                 if (ret < 0 && ret != -ENOTSUPP) {
 38                         dev_err(rtd->dev, "Failed to set sdw stream on %s\n",
 39                                 codec_dai->name);
 40                         goto err_set_stream;
 41                 }
 42         }
 43 
 44         return 0;
 45 
 46 err_set_stream:
 47         sdw_release_stream(sruntime);
 48 
 49         return ret;
 50 }
 51 EXPORT_SYMBOL_GPL(qcom_snd_sdw_startup);
 52 
 53 int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
 54                          struct sdw_stream_runtime *sruntime,
 55                          bool *stream_prepared)
 56 {
 57         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 58         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
 59         int ret;
 60 
 61         if (!sruntime)
 62                 return 0;
 63 
 64         switch (cpu_dai->id) {
 65         case WSA_CODEC_DMA_RX_0:
 66         case WSA_CODEC_DMA_RX_1:
 67         case RX_CODEC_DMA_RX_0:
 68         case RX_CODEC_DMA_RX_1:
 69         case TX_CODEC_DMA_TX_0:
 70         case TX_CODEC_DMA_TX_1:
 71         case TX_CODEC_DMA_TX_2:
 72         case TX_CODEC_DMA_TX_3:
 73                 break;
 74         default:
 75                 return 0;
 76         }
 77 
 78         if (*stream_prepared)
 79                 return 0;
 80 
 81         ret = sdw_prepare_stream(sruntime);
 82         if (ret)
 83                 return ret;
 84 
 85         /**
 86          * NOTE: there is a strict hw requirement about the ordering of port
 87          * enables and actual WSA881x PA enable. PA enable should only happen
 88          * after soundwire ports are enabled if not DC on the line is
 89          * accumulated resulting in Click/Pop Noise
 90          * PA enable/mute are handled as part of codec DAPM and digital mute.
 91          */
 92 
 93         ret = sdw_enable_stream(sruntime);
 94         if (ret) {
 95                 sdw_deprepare_stream(sruntime);
 96                 return ret;
 97         }
 98         *stream_prepared  = true;
 99 
100         return ret;
101 }
102 EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
103 
104 int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
105                            struct snd_pcm_hw_params *params,
106                            struct sdw_stream_runtime **psruntime)
107 {
108         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
109         struct snd_soc_dai *codec_dai;
110         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
111         struct sdw_stream_runtime *sruntime;
112         int i;
113 
114         switch (cpu_dai->id) {
115         case WSA_CODEC_DMA_RX_0:
116         case RX_CODEC_DMA_RX_0:
117         case RX_CODEC_DMA_RX_1:
118         case TX_CODEC_DMA_TX_0:
119         case TX_CODEC_DMA_TX_1:
120         case TX_CODEC_DMA_TX_2:
121         case TX_CODEC_DMA_TX_3:
122                 for_each_rtd_codec_dais(rtd, i, codec_dai) {
123                         sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
124                         if (sruntime != ERR_PTR(-ENOTSUPP))
125                                 *psruntime = sruntime;
126                 }
127                 break;
128         }
129 
130         return 0;
131 
132 }
133 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
134 
135 int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
136                          struct sdw_stream_runtime *sruntime, bool *stream_prepared)
137 {
138         struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
139         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
140 
141         switch (cpu_dai->id) {
142         case WSA_CODEC_DMA_RX_0:
143         case WSA_CODEC_DMA_RX_1:
144         case RX_CODEC_DMA_RX_0:
145         case RX_CODEC_DMA_RX_1:
146         case TX_CODEC_DMA_TX_0:
147         case TX_CODEC_DMA_TX_1:
148         case TX_CODEC_DMA_TX_2:
149         case TX_CODEC_DMA_TX_3:
150                 if (sruntime && *stream_prepared) {
151                         sdw_disable_stream(sruntime);
152                         sdw_deprepare_stream(sruntime);
153                         *stream_prepared = false;
154                 }
155                 break;
156         default:
157                 break;
158         }
159 
160         return 0;
161 }
162 EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
163 MODULE_DESCRIPTION("Qualcomm ASoC SoundWire helper functions");
164 MODULE_LICENSE("GPL");
165 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php