GNU Linux-libre 4.19.211-gnu1
[releases.git] / sound / soc / soc-utils.c
1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // soc-util.c  --  ALSA SoC Audio Layer utility functions
4 //
5 // Copyright 2009 Wolfson Microelectronics PLC.
6 //
7 // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 //         Liam Girdwood <lrg@slimlogic.co.uk>
9
10 #include <linux/platform_device.h>
11 #include <linux/export.h>
12 #include <sound/core.h>
13 #include <sound/pcm.h>
14 #include <sound/pcm_params.h>
15 #include <sound/soc.h>
16
17 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots)
18 {
19         return sample_size * channels * tdm_slots;
20 }
21 EXPORT_SYMBOL_GPL(snd_soc_calc_frame_size);
22
23 int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params)
24 {
25         int sample_size;
26
27         sample_size = snd_pcm_format_width(params_format(params));
28         if (sample_size < 0)
29                 return sample_size;
30
31         return snd_soc_calc_frame_size(sample_size, params_channels(params),
32                                        1);
33 }
34 EXPORT_SYMBOL_GPL(snd_soc_params_to_frame_size);
35
36 int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots)
37 {
38         return fs * snd_soc_calc_frame_size(sample_size, channels, tdm_slots);
39 }
40 EXPORT_SYMBOL_GPL(snd_soc_calc_bclk);
41
42 int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params)
43 {
44         int ret;
45
46         ret = snd_soc_params_to_frame_size(params);
47
48         if (ret > 0)
49                 return ret * params_rate(params);
50         else
51                 return ret;
52 }
53 EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk);
54
55 int snd_soc_component_enable_pin(struct snd_soc_component *component,
56                                  const char *pin)
57 {
58         struct snd_soc_dapm_context *dapm =
59                 snd_soc_component_get_dapm(component);
60         char *full_name;
61         int ret;
62
63         if (!component->name_prefix)
64                 return snd_soc_dapm_enable_pin(dapm, pin);
65
66         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
67         if (!full_name)
68                 return -ENOMEM;
69
70         ret = snd_soc_dapm_enable_pin(dapm, full_name);
71         kfree(full_name);
72
73         return ret;
74 }
75 EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
76
77 int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
78                                           const char *pin)
79 {
80         struct snd_soc_dapm_context *dapm =
81                 snd_soc_component_get_dapm(component);
82         char *full_name;
83         int ret;
84
85         if (!component->name_prefix)
86                 return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
87
88         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
89         if (!full_name)
90                 return -ENOMEM;
91
92         ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name);
93         kfree(full_name);
94
95         return ret;
96 }
97 EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
98
99 int snd_soc_component_disable_pin(struct snd_soc_component *component,
100                                   const char *pin)
101 {
102         struct snd_soc_dapm_context *dapm =
103                 snd_soc_component_get_dapm(component);
104         char *full_name;
105         int ret;
106
107         if (!component->name_prefix)
108                 return snd_soc_dapm_disable_pin(dapm, pin);
109
110         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
111         if (!full_name)
112                 return -ENOMEM;
113
114         ret = snd_soc_dapm_disable_pin(dapm, full_name);
115         kfree(full_name);
116
117         return ret;
118 }
119 EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
120
121 int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
122                                            const char *pin)
123 {
124         struct snd_soc_dapm_context *dapm =
125                 snd_soc_component_get_dapm(component);
126         char *full_name;
127         int ret;
128
129         if (!component->name_prefix)
130                 return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
131
132         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
133         if (!full_name)
134                 return -ENOMEM;
135
136         ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name);
137         kfree(full_name);
138
139         return ret;
140 }
141 EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
142
143 int snd_soc_component_nc_pin(struct snd_soc_component *component,
144                              const char *pin)
145 {
146         struct snd_soc_dapm_context *dapm =
147                 snd_soc_component_get_dapm(component);
148         char *full_name;
149         int ret;
150
151         if (!component->name_prefix)
152                 return snd_soc_dapm_nc_pin(dapm, pin);
153
154         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
155         if (!full_name)
156                 return -ENOMEM;
157
158         ret = snd_soc_dapm_nc_pin(dapm, full_name);
159         kfree(full_name);
160
161         return ret;
162 }
163 EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
164
165 int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
166                                       const char *pin)
167 {
168         struct snd_soc_dapm_context *dapm =
169                 snd_soc_component_get_dapm(component);
170         char *full_name;
171         int ret;
172
173         if (!component->name_prefix)
174                 return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
175
176         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
177         if (!full_name)
178                 return -ENOMEM;
179
180         ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name);
181         kfree(full_name);
182
183         return ret;
184 }
185 EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
186
187 int snd_soc_component_get_pin_status(struct snd_soc_component *component,
188                                      const char *pin)
189 {
190         struct snd_soc_dapm_context *dapm =
191                 snd_soc_component_get_dapm(component);
192         char *full_name;
193         int ret;
194
195         if (!component->name_prefix)
196                 return snd_soc_dapm_get_pin_status(dapm, pin);
197
198         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
199         if (!full_name)
200                 return -ENOMEM;
201
202         ret = snd_soc_dapm_get_pin_status(dapm, full_name);
203         kfree(full_name);
204
205         return ret;
206 }
207 EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
208
209 int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
210                                        const char *pin)
211 {
212         struct snd_soc_dapm_context *dapm =
213                 snd_soc_component_get_dapm(component);
214         char *full_name;
215         int ret;
216
217         if (!component->name_prefix)
218                 return snd_soc_dapm_force_enable_pin(dapm, pin);
219
220         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
221         if (!full_name)
222                 return -ENOMEM;
223
224         ret = snd_soc_dapm_force_enable_pin(dapm, full_name);
225         kfree(full_name);
226
227         return ret;
228 }
229 EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
230
231 int snd_soc_component_force_enable_pin_unlocked(
232                                         struct snd_soc_component *component,
233                                         const char *pin)
234 {
235         struct snd_soc_dapm_context *dapm =
236                 snd_soc_component_get_dapm(component);
237         char *full_name;
238         int ret;
239
240         if (!component->name_prefix)
241                 return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
242
243         full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
244         if (!full_name)
245                 return -ENOMEM;
246
247         ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name);
248         kfree(full_name);
249
250         return ret;
251 }
252 EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
253
254 static const struct snd_pcm_hardware dummy_dma_hardware = {
255         /* Random values to keep userspace happy when checking constraints */
256         .info                   = SNDRV_PCM_INFO_INTERLEAVED |
257                                   SNDRV_PCM_INFO_BLOCK_TRANSFER,
258         .buffer_bytes_max       = 128*1024,
259         .period_bytes_min       = PAGE_SIZE,
260         .period_bytes_max       = PAGE_SIZE*2,
261         .periods_min            = 2,
262         .periods_max            = 128,
263 };
264
265 static int dummy_dma_open(struct snd_pcm_substream *substream)
266 {
267         struct snd_soc_pcm_runtime *rtd = substream->private_data;
268
269         /* BE's dont need dummy params */
270         if (!rtd->dai_link->no_pcm)
271                 snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
272
273         return 0;
274 }
275
276 static const struct snd_pcm_ops dummy_dma_ops = {
277         .open           = dummy_dma_open,
278         .ioctl          = snd_pcm_lib_ioctl,
279 };
280
281 static const struct snd_soc_component_driver dummy_platform = {
282         .ops = &dummy_dma_ops,
283 };
284
285 static const struct snd_soc_component_driver dummy_codec = {
286         .idle_bias_on           = 1,
287         .use_pmdown_time        = 1,
288         .endianness             = 1,
289         .non_legacy_dai_naming  = 1,
290 };
291
292 #define STUB_RATES      SNDRV_PCM_RATE_8000_192000
293 #define STUB_FORMATS    (SNDRV_PCM_FMTBIT_S8 | \
294                         SNDRV_PCM_FMTBIT_U8 | \
295                         SNDRV_PCM_FMTBIT_S16_LE | \
296                         SNDRV_PCM_FMTBIT_U16_LE | \
297                         SNDRV_PCM_FMTBIT_S24_LE | \
298                         SNDRV_PCM_FMTBIT_U24_LE | \
299                         SNDRV_PCM_FMTBIT_S32_LE | \
300                         SNDRV_PCM_FMTBIT_U32_LE | \
301                         SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
302 /*
303  * The dummy CODEC is only meant to be used in situations where there is no
304  * actual hardware.
305  *
306  * If there is actual hardware even if it does not have a control bus
307  * the hardware will still have constraints like supported samplerates, etc.
308  * which should be modelled. And the data flow graph also should be modelled
309  * using DAPM.
310  */
311 static struct snd_soc_dai_driver dummy_dai = {
312         .name = "snd-soc-dummy-dai",
313         .playback = {
314                 .stream_name    = "Playback",
315                 .channels_min   = 1,
316                 .channels_max   = 384,
317                 .rates          = STUB_RATES,
318                 .formats        = STUB_FORMATS,
319         },
320         .capture = {
321                 .stream_name    = "Capture",
322                 .channels_min   = 1,
323                 .channels_max   = 384,
324                 .rates = STUB_RATES,
325                 .formats = STUB_FORMATS,
326          },
327 };
328
329 int snd_soc_dai_is_dummy(struct snd_soc_dai *dai)
330 {
331         if (dai->driver == &dummy_dai)
332                 return 1;
333         return 0;
334 }
335
336 static int snd_soc_dummy_probe(struct platform_device *pdev)
337 {
338         int ret;
339
340         ret = devm_snd_soc_register_component(&pdev->dev,
341                                               &dummy_codec, &dummy_dai, 1);
342         if (ret < 0)
343                 return ret;
344
345         ret = devm_snd_soc_register_component(&pdev->dev, &dummy_platform,
346                                               NULL, 0);
347
348         return ret;
349 }
350
351 static struct platform_driver soc_dummy_driver = {
352         .driver = {
353                 .name = "snd-soc-dummy",
354         },
355         .probe = snd_soc_dummy_probe,
356 };
357
358 static struct platform_device *soc_dummy_dev;
359
360 int __init snd_soc_util_init(void)
361 {
362         int ret;
363
364         soc_dummy_dev =
365                 platform_device_register_simple("snd-soc-dummy", -1, NULL, 0);
366         if (IS_ERR(soc_dummy_dev))
367                 return PTR_ERR(soc_dummy_dev);
368
369         ret = platform_driver_register(&soc_dummy_driver);
370         if (ret != 0)
371                 platform_device_unregister(soc_dummy_dev);
372
373         return ret;
374 }
375
376 void __exit snd_soc_util_exit(void)
377 {
378         platform_driver_unregister(&soc_dummy_driver);
379         platform_device_unregister(soc_dummy_dev);
380 }