1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sound/snd_core.h>
36 #include <sound/snd_pcm.h>
37 #include <sound/snd_io.h>
38 #include <sound/snd_misc.h>
39 #include <hal_osal.h>
40 #include <interrupt.h>
41 #include <hal_sem.h>
42 #include <hal_mem.h>
43 #include <hal_mutex.h>
44 
45 static LIST_HEAD(gCardList);
46 
snd_mutex_init(void)47 snd_mutex_t snd_mutex_init(void)
48 {
49     snd_mutex_t hal_mutex = NULL;
50 
51     hal_mutex = hal_mutex_create();
52     if (hal_mutex == NULL) {
53         snd_print("hal_mutex_create err.\n");
54     }
55     return hal_mutex;
56 }
57 
snd_mutex_lock_timeout(snd_mutex_t mutex,long ms)58 int snd_mutex_lock_timeout(snd_mutex_t mutex, long ms)
59 {
60     long ret;
61     const uint32_t timeout = ms / (1000 / CONFIG_HZ);
62     if (!mutex)
63         return -1;
64     snd_print("\n");
65     ret = hal_mutex_timedwait(mutex, timeout);
66 
67     return ret;
68 }
69 
snd_mutex_lock(snd_mutex_t mutex)70 int snd_mutex_lock(snd_mutex_t mutex)
71 {
72     int ret;
73     if (!mutex)
74         return -1;
75     snd_print("\n");
76     ret = hal_mutex_timedwait(mutex, 100);
77 
78     return ret;
79 }
80 
snd_mutex_unlock(snd_mutex_t mutex)81 void snd_mutex_unlock(snd_mutex_t mutex)
82 {
83     if (!mutex)
84         return;
85     snd_print("\n");
86     hal_mutex_unlock(mutex);
87 }
88 
snd_mutex_destroy(snd_mutex_t mutex)89 void snd_mutex_destroy(snd_mutex_t mutex)
90 {
91     if (!mutex)
92         return;
93     hal_mutex_delete(mutex);
94 }
95 
snd_schd_init(void)96 snd_schd_t snd_schd_init(void)
97 {
98     snd_schd_t schd;
99 
100     schd = snd_malloc(sizeof(*schd));
101     if (!schd)
102         return NULL;
103     schd->waiting = 0;
104     schd->sem = hal_sem_create(0);
105     if (schd->sem == NULL) {
106         snd_free(schd);
107         snd_err("sem init err.\n");
108         return NULL;
109     }
110     return schd;
111 }
112 
snd_schd_timeout(snd_schd_t schd,long ms)113 int snd_schd_timeout(snd_schd_t schd, long ms)
114 {
115     int ret;
116     const uint32_t timeout = ms / (1000 / CONFIG_HZ);
117     if (!schd)
118         return -1;
119     snd_print("\n");
120     schd->waiting = 1;
121     ret = hal_sem_timedwait(schd->sem, timeout);
122     if (ret == 0)
123         return 0;
124     return -1;
125 }
126 
snd_schd_wakeup(snd_schd_t schd)127 void snd_schd_wakeup(snd_schd_t schd)
128 {
129     int ret;
130     /* may call with irq disabled, so use xSemaphoreGiveFromISR */
131     if (!schd || !schd->waiting)
132         return;
133     snd_print("\n");
134     ret = hal_sem_post(schd->sem);
135     if (ret == 0) {
136         return;
137     }
138 }
139 
snd_schd_destroy(snd_schd_t schd)140 void snd_schd_destroy(snd_schd_t schd)
141 {
142     if (!schd)
143         return;
144     snd_print("\n");
145     hal_sem_delete(schd->sem);
146     snd_free(schd);
147 }
148 
snd_pcm_stream_lock(struct snd_pcm_substream * substream)149 static void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
150 {
151     hal_spin_lock(&substream->lock);
152 }
153 
snd_pcm_stream_unlock(struct snd_pcm_substream * substream)154 static void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
155 {
156     hal_spin_unlock(&substream->lock);
157 }
158 
snd_pcm_stream_lock_irq(struct snd_pcm_substream * substream)159 void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
160 {
161     snd_lock_debug("\n");
162     hal_local_irq_disable();
163     snd_pcm_stream_lock(substream);
164 }
165 
snd_pcm_stream_unlock_irq(struct snd_pcm_substream * substream)166 void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
167 {
168     snd_lock_debug("\n");
169     snd_pcm_stream_unlock(substream);
170     hal_local_irq_enable();
171 }
172 
_snd_pcm_stream_lock_irqsave(struct snd_pcm_substream * substream)173 hal_irq_state_t _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
174 {
175     hal_irq_state_t flags = 0;
176 
177     snd_lock_debug("\n");
178     hal_local_irq_save(flags);
179     snd_pcm_stream_lock(substream);
180     return flags;
181 }
182 
snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream * substream,unsigned long flags)183 void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
184                     unsigned long flags)
185 {
186     snd_lock_debug("\n");
187     snd_pcm_stream_unlock(substream);
188     hal_local_irq_restore(flags);
189 }
190 
snd_set_runtime_hwparams(struct snd_pcm_substream * substream,const struct snd_pcm_hardware * hw)191 void snd_set_runtime_hwparams(struct snd_pcm_substream *substream,
192             const struct snd_pcm_hardware *hw)
193 {
194     struct snd_pcm_runtime *runtime = substream->runtime;
195 
196     runtime->hw.info = hw->info;
197     runtime->hw.formats = hw->formats;
198     runtime->hw.period_bytes_min = hw->period_bytes_min;
199     runtime->hw.period_bytes_max = hw->period_bytes_max;
200     runtime->hw.periods_min = hw->periods_min;
201     runtime->hw.periods_max = hw->periods_max;
202     runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
203     return;
204 }
205 
soc_pcm_init_runtime_hw_constrains(struct snd_pcm_hardware * hw,struct snd_pcm_hw_constrains * cons)206 static int soc_pcm_init_runtime_hw_constrains(struct snd_pcm_hardware *hw,
207                 struct snd_pcm_hw_constrains *cons)
208 {
209     union snd_interval *interval_access = &cons->intervals[SND_PCM_HW_PARAM_ACCESS];
210     if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
211         interval_access->mask |= 1 << SND_PCM_ACCESS_RW_INTERLEAVED;
212     if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
213         interval_access->mask |= 1 << SND_PCM_ACCESS_RW_NONINTERLEAVED;
214     if (hw->info & SNDRV_PCM_INFO_MMAP) {
215         if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
216             interval_access->mask |= 1 << SND_PCM_ACCESS_MMAP_INTERLEAVED;
217         if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
218             interval_access->mask |= 1 << SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
219     }
220 
221     cons->intervals[SND_PCM_HW_PARAM_FORMAT].mask = hw->formats;
222     cons->intervals[SND_PCM_HW_PARAM_CHANNELS].range.min = hw->channels_min;
223     cons->intervals[SND_PCM_HW_PARAM_CHANNELS].range.max = hw->channels_max;
224     cons->intervals[SND_PCM_HW_PARAM_RATE].range.min = hw->rate_min;
225     cons->intervals[SND_PCM_HW_PARAM_RATE].range.max = hw->rate_max;
226     cons->intervals[SND_PCM_HW_PARAM_PERIOD_BYTES].range.min = hw->period_bytes_min;
227     cons->intervals[SND_PCM_HW_PARAM_PERIOD_BYTES].range.max = hw->period_bytes_max;
228     cons->intervals[SND_PCM_HW_PARAM_PERIODS].range.min = hw->periods_min;
229     cons->intervals[SND_PCM_HW_PARAM_PERIODS].range.max = hw->periods_max;
230 
231     cons->intervals[SND_PCM_HW_PARAM_BUFFER_BYTES].range.max = hw->buffer_bytes_max;
232 
233     cons->intervals[SND_PCM_HW_PARAM_SAMPLE_BITS].range.min =
234             (uint32_t)snd_pcm_format_physical_width(__pcm_ffs(hw->formats));
235     cons->intervals[SND_PCM_HW_PARAM_SAMPLE_BITS].range.max =
236             (uint32_t)snd_pcm_format_physical_width(__fls(hw->formats));
237 
238     return 0;
239 }
240 
soc_pcm_init_runtime_hw(struct snd_pcm_substream * substream)241 static int soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
242 {
243     struct snd_dai *cpu_dai, *codec_dai;
244     struct snd_pcm_stream *cpu_stream, *codec_stream;
245     struct snd_pcm_runtime *runtime = substream->runtime;
246     struct snd_pcm_hardware *hw = &runtime->hw;
247     unsigned int rates = (~0U);
248 
249     cpu_dai = substream->pcm->card->platform->cpu_dai;
250     codec_dai = substream->pcm->card->codec->codec_dai;
251     /* ignore multi codecs */
252     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
253         cpu_stream = &cpu_dai->playback;
254         codec_stream = &codec_dai->playback;
255     } else {
256         cpu_stream = &cpu_dai->capture;
257         codec_stream = &codec_dai->capture;
258     }
259 
260     hw->channels_min = max(cpu_stream->channels_min, codec_stream->channels_min);
261     hw->channels_max = min(cpu_stream->channels_max, codec_stream->channels_max);
262     hw->formats = cpu_stream->formats & codec_stream->formats;
263     rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates);
264     hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_stream->rates);
265     snd_pcm_limit_hw_rates(runtime);
266 
267     hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min);
268     hw->rate_max = min(codec_stream->rate_max, cpu_stream->rate_max);
269 
270     /* fill in hw constrains */
271     soc_pcm_init_runtime_hw_constrains(hw, &runtime->hw_constrains);
272 
273     return 0;
274 }
275 
soc_pcm_open(struct snd_pcm_substream * substream)276 static int soc_pcm_open(struct snd_pcm_substream *substream)
277 {
278     int ret = 0;
279     struct snd_dai *cpu_dai, *codec_dai;
280     struct snd_platform *platform;
281 
282     snd_print("\n");
283     platform = substream->pcm->card->platform;
284     cpu_dai = platform->cpu_dai;
285     codec_dai = substream->pcm->card->codec->codec_dai;
286     /* TODO: pinctrl default state */
287 
288     /*snd_mutex_lock(runtime->pcm_mutex);*/
289     if (cpu_dai->ops->startup) {
290         ret = cpu_dai->ops->startup(substream, cpu_dai);
291         if (ret < 0) {
292             snd_err("cpu_dai startup failed\n");
293             goto _end_lock;
294         }
295     }
296     if (platform->ops->open) {
297         ret = platform->ops->open(substream);
298         if (ret < 0) {
299             snd_err("platform open failed\n");
300             goto _end_lock;
301         }
302     }
303     if (codec_dai->ops->startup) {
304         ret = codec_dai->ops->startup(substream, codec_dai);
305         if (ret < 0) {
306             snd_err("codec_dai startup failed\n");
307             goto _end_lock;
308         }
309     }
310     soc_pcm_init_runtime_hw(substream);
311 
312     snd_print("open %s stream\n", substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
313                     "Playback" : "Capture");
314 _end_lock:
315     /*snd_mutex_unlock(runtime->pcm_mutex);*/
316 
317     return ret;
318 }
319 
soc_dai_set_sysclk(struct snd_dai * dai,int clk_id,unsigned int freq,int dir)320 static int soc_dai_set_sysclk(struct snd_dai *dai, int clk_id,
321                 unsigned int freq, int dir)
322 {
323     if ((dai == NULL) || (dai->ops == NULL))
324         return -EINVAL;
325     if (dai->ops->set_sysclk)
326         return dai->ops->set_sysclk(dai, clk_id, freq, dir);
327     return 0;
328 }
329 
soc_dai_set_pll(struct snd_dai * dai,int pll_id,int source,unsigned int freq_in,int freq_out)330 static int soc_dai_set_pll(struct snd_dai *dai, int pll_id, int source,
331                 unsigned int freq_in, int freq_out)
332 {
333     if ((dai == NULL) || (dai->ops == NULL))
334         return -EINVAL;
335     if (dai->ops->set_pll)
336         return dai->ops->set_pll(dai, pll_id, source, freq_in, freq_out);
337     return 0;
338 }
339 
snd_soc_dai_set_fmt(struct snd_dai * dai,unsigned int fmt)340 int snd_soc_dai_set_fmt(struct snd_dai *dai, unsigned int fmt)
341 {
342     if ((dai == NULL) || (dai->ops == NULL))
343         return -EINVAL;
344     if (dai->ops->set_fmt)
345         return dai->ops->set_fmt(dai, fmt);
346     return 0;
347 }
348 
soc_dai_set_clkdiv(struct snd_dai * dai,int div_id,int div)349 static int soc_dai_set_clkdiv(struct snd_dai *dai, int div_id, int div)
350 {
351     if ((dai == NULL) || (dai->ops == NULL))
352         return -EINVAL;
353     if (dai->ops->set_clkdiv)
354         return dai->ops->set_clkdiv(dai, div_id, div);
355     return 0;
356 }
357 
soc_pcm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)358 static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
359                 struct snd_pcm_hw_params *params)
360 {
361     int ret;
362     unsigned int freq, clk_div;
363     struct snd_dai *codec_dai, *cpu_dai;
364     struct snd_platform *platform;
365     codec_dai = substream->pcm->card->codec->codec_dai;
366     platform = substream->pcm->card->platform;
367     cpu_dai = platform->cpu_dai;
368 
369     snd_print("\n");
370     /*snd_mutex_lock(runtime->pcm_mutex);*/
371     switch (params_rate(params)) {
372     case 8000:
373     case 12000:
374     case 16000:
375     case 24000:
376     case 32000:
377     case 48000:
378     case 64000:
379     case 96000:
380     case 192000:
381         freq = 24576000;
382         break;
383     case 11025:
384     case 22050:
385     case 44100:
386     case 88200:
387         freq = 22579200;
388         break;
389     default:
390         snd_err("unsupport params rate:%d\n", params_rate(params));
391         ret = -EINVAL;
392         goto _end_lock;
393     }
394 
395     ret = soc_dai_set_sysclk(cpu_dai, 0, freq, 0);
396     if (ret < 0) {
397         snd_err("cpu_dai set sysclk failed\n");
398         goto _end_lock;
399     }
400     ret = soc_dai_set_sysclk(codec_dai, 0, freq, 0);
401     if (ret < 0) {
402         snd_err("codec_dai set sysclk failed\n");
403         goto _end_lock;
404     }
405     ret = soc_dai_set_pll(cpu_dai, 0, 0, freq, freq);
406     if (ret < 0) {
407         snd_err("cpu_dai set pll failed\n");
408         goto _end_lock;
409     }
410     ret = soc_dai_set_pll(codec_dai, 0, 0, freq, freq);
411     if (ret < 0) {
412         snd_err("codec_dai set pll failed\n");
413         goto _end_lock;
414     }
415     clk_div = freq / params_rate(params);
416     ret = soc_dai_set_clkdiv(cpu_dai, 0, clk_div);
417     if (ret < 0) {
418         snd_err("cpu_dai set clkdiv failed\n");
419         goto _end_lock;
420     }
421     ret = soc_dai_set_clkdiv(codec_dai, 0, clk_div);
422     if (ret < 0) {
423         snd_err("codec_dai set clkdiv failed\n");
424         goto _end_lock;
425     }
426 
427     if (codec_dai->ops->hw_params) {
428         ret = codec_dai->ops->hw_params(substream, params, codec_dai);
429         if (ret < 0) {
430             snd_err("codec_dai set hw params failed\n");
431             goto _end_lock;
432         }
433     }
434     if (cpu_dai->ops->hw_params) {
435         ret = cpu_dai->ops->hw_params(substream, params, cpu_dai);
436         if (ret < 0) {
437             snd_err("cpu_dai set hw params failed\n");
438             goto cpu_dai_err;
439         }
440     }
441     if (platform->ops->hw_params) {
442         ret = platform->ops->hw_params(substream, params);
443         if (ret < 0) {
444             snd_err("platform set hw params failed\n");
445             goto platform_err;
446         }
447     }
448 
449     return ret;
450 
451 platform_err:
452     if (cpu_dai->ops->hw_free)
453         cpu_dai->ops->hw_free(substream, cpu_dai);
454 cpu_dai_err:
455     if (codec_dai->ops->hw_free)
456         codec_dai->ops->hw_free(substream, codec_dai);
457 _end_lock:
458     /*snd_mutex_unlock(runtime->pcm_mutex);*/
459 
460     return ret;
461 }
462 
soc_pcm_prepare(struct snd_pcm_substream * substream)463 static int soc_pcm_prepare(struct snd_pcm_substream *substream)
464 {
465     int ret = 0;
466     struct snd_dai *codec_dai, *cpu_dai;
467     struct snd_platform *platform;
468 
469     snd_print("\n");
470     /*snd_mutex_lock(runtime->pcm_mutex);*/
471     platform = substream->pcm->card->platform;
472     codec_dai = substream->pcm->card->codec->codec_dai;
473     cpu_dai = platform->cpu_dai;
474 
475     if (platform->ops->prepare) {
476         ret = platform->ops->prepare(substream);
477         if (ret < 0) {
478             snd_err("platform prepare failed\n");
479             goto _end_lock;
480         }
481     }
482 
483     if (codec_dai->ops->prepare) {
484         ret = codec_dai->ops->prepare(substream, codec_dai);
485         if (ret < 0) {
486             snd_err("codec_dai prepare failed\n");
487             goto _end_lock;
488         }
489     }
490     if (cpu_dai->ops->prepare) {
491         ret = cpu_dai->ops->prepare(substream, cpu_dai);
492         if (ret < 0) {
493             snd_err("cpu_dai prepare failed\n");
494             goto _end_lock;
495         }
496     }
497 
498     if (codec_dai->ops->dapm_control) {
499         ret = codec_dai->ops->dapm_control(substream, codec_dai, 1);
500         if (ret < 0) {
501             snd_err("codec_dai dapm_control failed\n");
502             goto _end_lock;
503         }
504     }
505 
506 _end_lock:
507     /*snd_mutex_unlock(runtime->pcm_mutex);*/
508     return ret;
509 }
510 
soc_pcm_trigger(struct snd_pcm_substream * substream,int cmd)511 static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
512 {
513     int ret = 0;
514     struct snd_dai *codec_dai, *cpu_dai;
515     struct snd_platform *platform;
516 
517     snd_print("\n");
518     platform = substream->pcm->card->platform;
519     codec_dai = substream->pcm->card->codec->codec_dai;
520     cpu_dai = platform->cpu_dai;
521 
522     if (codec_dai->ops->trigger) {
523         ret = codec_dai->ops->trigger(substream, cmd, codec_dai);
524         if (ret < 0) {
525             snd_err("codec_dai trigger failed\n");
526             return ret;
527         }
528     }
529 
530     if (platform->ops->trigger) {
531         ret = platform->ops->trigger(substream, cmd);
532         if (ret < 0) {
533             snd_err("platform trigger failed\n");
534             return ret;
535         }
536     }
537 
538     if (cpu_dai->ops->trigger) {
539         ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai);
540         if (ret < 0) {
541             snd_err("cpu_dai trigger failed\n");
542             return ret;
543         }
544     }
545     return ret;
546 }
547 
soc_pcm_hw_free(struct snd_pcm_substream * substream)548 static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
549 {
550     int ret = 0;
551     struct snd_dai *codec_dai, *cpu_dai;
552     struct snd_platform *platform;
553 
554     snd_print("\n");
555     platform = substream->pcm->card->platform;
556     codec_dai = substream->pcm->card->codec->codec_dai;
557     cpu_dai = platform->cpu_dai;
558 
559     if (platform->ops->hw_free) {
560         ret = platform->ops->hw_free(substream);
561         if (ret < 0) {
562             snd_err("platform hw free failed\n");
563             return ret;
564         }
565     }
566 
567     if (codec_dai->ops->hw_free) {
568         ret = codec_dai->ops->hw_free(substream, codec_dai);
569         if (ret < 0) {
570             snd_err("codec_dai hw free failed\n");
571             return ret;
572         }
573     }
574     if (cpu_dai->ops->hw_free) {
575         ret = cpu_dai->ops->hw_free(substream, cpu_dai);
576         if (ret < 0) {
577             snd_err("cpu_dai hw free failed\n");
578             return ret;
579         }
580     }
581 
582     return ret;
583 }
584 
soc_pcm_close(struct snd_pcm_substream * substream)585 static int soc_pcm_close(struct snd_pcm_substream *substream)
586 {
587     struct snd_dai *cpu_dai, *codec_dai;
588     struct snd_platform *platform;
589 
590     snd_print("\n");
591     platform = substream->pcm->card->platform;
592     cpu_dai = platform->cpu_dai;
593     codec_dai = substream->pcm->card->codec->codec_dai;
594     if (cpu_dai->ops->shutdown)
595         cpu_dai->ops->shutdown(substream, cpu_dai);
596     if (codec_dai->ops->shutdown)
597         codec_dai->ops->shutdown(substream, codec_dai);
598     if (platform->ops->close)
599         platform->ops->close(substream);
600 
601     /* dapm stop */
602     if (codec_dai->ops->dapm_control)
603         codec_dai->ops->dapm_control(substream, codec_dai, 0);
604 
605     /* TODO: pinctrl sleep state */
606 
607     return 0;
608 }
609 
soc_pcm_pointer(struct snd_pcm_substream * substream)610 static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
611 {
612     struct snd_platform *platform;
613     snd_pcm_uframes_t offset = 0;
614 
615     snd_print("\n");
616     platform = substream->pcm->card->platform;
617 
618     if (platform->ops->pointer)
619         offset = platform->ops->pointer(substream);
620 
621     return offset;
622 }
623 
soc_pcm_ioctl(struct snd_pcm_substream * substream,unsigned int cmd,void * arg)624 static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
625                      unsigned int cmd, void *arg)
626 {
627     struct snd_platform *platform;
628 
629     snd_print("\n");
630     platform = substream->pcm->card->platform;
631 
632         if (platform->ops && platform->ops->ioctl)
633                 return platform->ops->ioctl(substream, cmd, arg);
634     /* FIXME:snd_pcm_lib_ioctl should be called, but it has been called in ksnd_pcm_reset. */
635     return -EOPNOTSUPP;
636         /* return snd_pcm_lib_ioctl(substream, cmd, arg); */
637 }
638 
snd_pcm_new_stream(struct snd_pcm * pcm,int stream,int substream_count)639 int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
640 {
641     struct snd_pcm_substream *substream;
642     static struct snd_pcm_ops pcm_ops = {
643         .open       = soc_pcm_open,
644         .hw_params  = soc_pcm_hw_params,
645         .prepare    = soc_pcm_prepare,
646         .trigger    = soc_pcm_trigger,
647         .hw_free    = soc_pcm_hw_free,
648         .pointer    = soc_pcm_pointer,
649         .close      = soc_pcm_close,
650         .ioctl      = soc_pcm_ioctl,
651     };
652 
653     if (!substream_count)
654         return 0;
655     substream = snd_malloc(sizeof(struct snd_pcm_substream));
656     if (!substream) {
657         snd_err("alloc substream failed !\n");
658         return -1;
659     }
660     /* hal_spin_lock_init(&substream->lock); */
661     substream->pcm = pcm;
662     substream->ops = &pcm_ops;
663     substream->stream = stream;
664     substream->ref_count = 0;
665     pcm->streams[stream] = substream;
666     snprintf(substream->name, sizeof(substream->name), "%s %s", pcm->id,
667         (stream == SNDRV_PCM_STREAM_PLAYBACK)? "Playback" : "Capture");
668     snd_print("new stream\n");
669     return 0;
670 }
671 
snd_pcm_free_stream(struct snd_pcm_substream * substream)672 static void snd_pcm_free_stream(struct snd_pcm_substream * substream)
673 {
674     snd_print("\n");
675     if (!substream)
676         return;
677     snd_free(substream);
678 }
679 
snd_pcm_free(struct snd_pcm * pcm)680 static int snd_pcm_free(struct snd_pcm *pcm)
681 {
682     snd_print("\n");
683     if (pcm->private_free)
684         pcm->private_free(pcm);
685     snd_pcm_free_stream(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]);
686     snd_pcm_free_stream(pcm->streams[SNDRV_PCM_STREAM_CAPTURE]);
687     list_del(&pcm->list);
688     snd_mutex_destroy(pcm->open_mutex);
689     /*snd_mutex_destroy(pcm->pcm_mutex);*/
690     snd_free(pcm);
691     return 0;
692 }
693 
snd_ctl_free(struct snd_card * card)694 static int snd_ctl_free(struct snd_card *card)
695 {
696     struct snd_ctl *ctl;
697     struct snd_kcontrol *c = NULL, *temp;
698 
699     ctl = card->ctl;
700     if (!ctl)
701         return 0;
702     list_for_each_entry_safe(c, temp, &ctl->controls, list) {
703         snd_ctl_remove_elem(ctl, c);
704     }
705     snd_mutex_destroy(ctl->ctl_mutex);
706     snd_free(ctl);
707     card->ctl = NULL;
708 
709     return 0;
710 }
711 
snd_ctl_kcontrol_user_get(struct snd_kcontrol * kcontrol,struct snd_ctl_info * info)712 static int snd_ctl_kcontrol_user_get(struct snd_kcontrol *kcontrol, struct snd_ctl_info *info)
713 {
714     if (!kcontrol->count || !kcontrol->private_data) {
715         snd_err("kcontrol count=%d, private_data=%p\n",
716             kcontrol->count, kcontrol->private_data);
717         return -1;
718     }
719 
720     info->value = ((unsigned long *)kcontrol->private_data)[0];
721     if (info->private_data)
722         memcpy(info->private_data, kcontrol->private_data, kcontrol->count * sizeof(unsigned long));
723     else
724         info->private_data = (unsigned long *)kcontrol->private_data;
725     info->id = kcontrol->id;
726     info->count  = kcontrol->count;
727     info->name = kcontrol->name;
728     info->max = kcontrol->max;
729     info->min = kcontrol->min;
730     snd_info("count=%d, value:0x%x\n", kcontrol->count, info->value);
731 
732     return 0;
733 }
734 
snd_ctl_kcontrol_user_set_value(struct snd_kcontrol * kcontrol,unsigned long value,int index)735 static inline int snd_ctl_kcontrol_user_set_value(struct snd_kcontrol *kcontrol,
736                         unsigned long value, int index)
737 {
738     unsigned long *user_value;
739     if (value < kcontrol->min || value > kcontrol->max) {
740         snd_err("invalid range. min:%d, max:%d, value:%lu\n",
741             kcontrol->min, kcontrol->max, value);
742         return -1;
743     }
744     user_value = (unsigned long*)kcontrol->private_data;
745     user_value[index] = value;
746 
747     return 0;
748 }
749 
snd_ctl_kcontrol_user_set(struct snd_kcontrol * kcontrol,unsigned long val)750 static int snd_ctl_kcontrol_user_set(struct snd_kcontrol *kcontrol, unsigned long val)
751 {
752     unsigned long*user_value;
753     int i;
754     if (!kcontrol->count || !kcontrol->private_data) {
755         snd_err("kcontrol count=%d, private_data=%p\n",
756             kcontrol->count, kcontrol->private_data);
757         return -1;
758     }
759 
760     if (kcontrol->count == 1) {
761         user_value = (unsigned long *)&val;
762         return snd_ctl_kcontrol_user_set_value(kcontrol, *user_value, 0);
763     }
764 
765     for (i = 0; i < kcontrol->count; i++) {
766         user_value = (unsigned long *)val;
767         if (snd_ctl_kcontrol_user_set_value(kcontrol, user_value[i], i) < 0)
768             return -1;
769     }
770 
771     return 0;
772 }
773 
snd_ctl_kcontrol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_info * info)774 static int snd_ctl_kcontrol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_info *info)
775 {
776     unsigned int val = 0;
777 
778     if (kcontrol->private_data_type == SND_MODULE_CODEC) {
779         struct snd_codec *codec = kcontrol->private_data;
780         val = snd_codec_read(codec, kcontrol->reg);
781     } else if (kcontrol->private_data_type == SND_MODULE_PLATFORM) {
782         struct snd_platform *platform = kcontrol->private_data;
783         val = snd_platform_read(platform, kcontrol->reg);
784     } else {
785         snd_err("%s invalid kcontrol data type = %d.\n", __func__,
786                 kcontrol->private_data_type);
787     }
788 
789     snd_kcontrol_to_snd_ctl_info(kcontrol, info, val);
790 
791     return 0;
792 }
793 
snd_ctl_enum_get(struct snd_kcontrol * kcontrol,struct snd_ctl_info * info)794 static int snd_ctl_enum_get(struct snd_kcontrol *kcontrol,
795                 struct snd_ctl_info *info)
796 {
797     unsigned int val = 0;
798 
799     if (kcontrol->type != SND_CTL_ELEM_TYPE_ENUMERATED) {
800         snd_err("invalid kcontrol type = %d.\n", kcontrol->type);
801         return -EINVAL;
802     }
803 
804     if (kcontrol->private_data_type == SND_MODULE_CODEC) {
805         struct snd_codec *codec = kcontrol->private_data;
806         val = snd_codec_read(codec, kcontrol->reg);
807     } else if (kcontrol->private_data_type == SND_MODULE_PLATFORM) {
808         struct snd_platform *platform = kcontrol->private_data;
809         val = snd_platform_read(platform, kcontrol->reg);
810     } else {
811         snd_err("%s invalid kcontrol data type = %d.\n", __func__,
812                 kcontrol->private_data_type);
813     }
814 
815     snd_kcontrol_to_snd_ctl_info(kcontrol, info, val);
816 
817     return 0;
818 }
819 
snd_ctl_enum_set(struct snd_kcontrol * kcontrol,unsigned long val)820 static int snd_ctl_enum_set(struct snd_kcontrol *kcontrol, unsigned long val)
821 {
822     if (kcontrol->type != SND_CTL_ELEM_TYPE_ENUMERATED) {
823         snd_err("invalid kcontrol type = %d.\n", kcontrol->type);
824         return -EINVAL;
825     }
826 
827     if (val >= kcontrol->items) {
828         snd_err("invalid kcontrol items = %ld.\n", val);
829         return -EINVAL;
830     }
831 
832     if (kcontrol->private_data_type == SND_MODULE_CODEC) {
833         struct snd_codec *codec = kcontrol->private_data;
834         snd_codec_update_bits(codec, kcontrol->reg,
835                 (kcontrol->mask << kcontrol->shift),
836                 ((unsigned int)val << kcontrol->shift));
837     } else if (kcontrol->private_data_type == SND_MODULE_PLATFORM) {
838         struct snd_platform *platform = kcontrol->private_data;
839         snd_platform_update_bits(platform, kcontrol->reg,
840                 (kcontrol->mask << kcontrol->shift),
841                 ((unsigned int)val << kcontrol->shift));
842     } else {
843         snd_err("invalid kcontrol data type = %d.\n",
844                 kcontrol->private_data_type);
845         return -EINVAL;
846     }
847     kcontrol->value = val & kcontrol->mask;
848 
849     snd_info("mask:0x%x, shift:%d, value:0x%x\n",
850             kcontrol->mask, kcontrol->shift, kcontrol->value);
851 
852     return 0;
853 }
854 
snd_kcontrol_to_snd_ctl_info(struct snd_kcontrol * kcontrol,struct snd_ctl_info * info,unsigned long value)855 void snd_kcontrol_to_snd_ctl_info(struct snd_kcontrol *kcontrol,
856             struct snd_ctl_info *info, unsigned long value)
857 {
858     info->id = kcontrol->id;
859     info->type = kcontrol->type;
860 
861     info->value = (unsigned long)((value >> kcontrol->shift) & kcontrol->mask);
862     if (info->type == SND_CTL_ELEM_TYPE_ENUMERATED) {
863         if (info->value >= kcontrol->items)
864             info->value = kcontrol->items - 1;
865     } else {
866         if (info->value > kcontrol->max)
867             info->value = kcontrol->max;
868         else if (info->value < kcontrol->min)
869             info->value = kcontrol->min;
870     }
871     info->name = kcontrol->name;
872     info->min = kcontrol->min;
873     info->max = kcontrol->max;
874     info->count = kcontrol->count;
875     info->items = kcontrol->items;
876     info->texts = kcontrol->texts;
877     snd_info("id:%d, type:%d, name:%s, value:0x%x, min:0x%x, max:0x%x, count:0x%x, items:0x%x\n",
878         kcontrol->id, kcontrol->type, info->name, info->value,
879         info->min, info->max, info->count, info->items);
880 }
881 
882 
snd_ctl_kcontrol_set(struct snd_kcontrol * kcontrol,unsigned long val)883 static int snd_ctl_kcontrol_set(struct snd_kcontrol *kcontrol, unsigned long val)
884 {
885     if (kcontrol->private_data_type == SND_MODULE_CODEC) {
886         struct snd_codec *codec = kcontrol->private_data;
887         snd_codec_update_bits(codec, kcontrol->reg,
888                 (kcontrol->mask << kcontrol->shift),
889                 ((unsigned int)val << kcontrol->shift));
890     } else {
891         struct snd_platform *platform = kcontrol->private_data;
892         snd_platform_update_bits(platform, kcontrol->reg,
893                 (kcontrol->mask << kcontrol->shift),
894                 ((unsigned int)val << kcontrol->shift));
895     }
896     snd_info("mask:0x%x, shitf:%d, value:0x%x\n",
897             kcontrol->mask, kcontrol->shift, val);
898     return 0;
899 }
900 
add_controls(struct snd_ctl * ctl,struct snd_kcontrol * control)901 static inline void add_controls(struct snd_ctl *ctl, struct snd_kcontrol *control)
902 {
903     if (control->private_data_type == SND_MODULE_USER) {
904         struct snd_ctl_info info;
905 
906         memset(&info, 0, sizeof(struct snd_ctl_info));
907         info.type = control->type;
908         info.count = control->count;
909         info.name = control->name;
910         info.max = control->max;
911         info.min = control->min;
912         /* initialize value, use reg instead */
913         info.value = control->reg;
914         if (snd_ctl_add_elem(ctl, &info) < 0)
915             snd_err("add user kcontrol(%s) failed\n", control->name);
916     } else {
917         switch (control->type) {
918         case SND_CTL_ELEM_TYPE_INTEGER:
919             control->mask = ((1 << __fls(control->max)) - 1);
920             if (!control->get)
921                 control->get = snd_ctl_kcontrol_get;
922             if (!control->set)
923                 control->set = snd_ctl_kcontrol_set;
924             break;
925         case SND_CTL_ELEM_TYPE_ENUMERATED:
926             if (control->mask == SND_CTL_ENUM_AUTO_MASK)
927                 control->mask = ((1 << __pcm_ffs(control->items)) - 1);
928             if (!control->get)
929                 control->get = snd_ctl_enum_get;
930             if (!control->set)
931                 control->set = snd_ctl_enum_set;
932             break;
933         default:
934             snd_err("kcontrol(%s) type invalid.\n", control->name);
935             break;
936         }
937         control->id = ctl->controls_num++;
938         list_add_tail(&control->list, &ctl->controls);
939     }
940 }
941 
snd_ctl_add_controls(struct snd_card * card,struct snd_ctl * ctl)942 static int snd_ctl_add_controls(struct snd_card *card, struct snd_ctl *ctl)
943 {
944     if (card->codec->controls) {
945         int i;
946         for (i = 0; i < card->codec->num_controls; i++) {
947             struct snd_kcontrol *control = NULL;
948 
949             control = &card->codec->controls[i];
950             if (!control->private_data_type) {
951                 control->private_data_type = SND_MODULE_CODEC;
952                 control->private_data = card->codec;
953             }
954             add_controls(ctl, control);
955         }
956     }
957     if (card->platform->controls) {
958         int i;
959         for (i = 0; i < card->platform->num_controls; i++) {
960             struct snd_kcontrol *control = NULL;
961 
962             control = &card->platform->controls[i];
963             if (!control->private_data_type) {
964                 control->private_data_type = SND_MODULE_PLATFORM;
965                 control->private_data = card->platform;
966             }
967             add_controls(ctl, control);
968         }
969     }
970 
971     return 0;
972 }
973 
snd_ctl_remove_elem(struct snd_ctl * ctl,struct snd_kcontrol * control)974 int snd_ctl_remove_elem(struct snd_ctl *ctl, struct snd_kcontrol *control)
975 {
976     if (control->dynamic != 1)
977         return -1;
978 
979     list_del(&control->list);
980     if (control->name)
981         snd_free((void *)control->name);
982     if (control->private_data)
983         snd_free(control->private_data);
984     snd_free(control);
985     return 0;
986 }
987 
snd_ctl_add_elem(struct snd_ctl * ctl,struct snd_ctl_info * info)988 int snd_ctl_add_elem(struct snd_ctl *ctl, struct snd_ctl_info *info)
989 {
990     struct snd_kcontrol *control;
991 
992     control = snd_malloc(sizeof(struct snd_kcontrol));
993     if (!control) {
994         snd_err("no memory\n");
995         return -ENOMEM;
996     }
997 
998     if (!info->count) {
999         snd_info("unknown count, default 1.\n");
1000         info->count = 1;
1001     }
1002     control->dynamic = 1;
1003     control->name = (const unsigned char *)snd_strdup((void *)info->name);
1004     if (!control->name) {
1005         snd_err("no memory\n");
1006         goto err;
1007     }
1008     control->private_data_type = SND_MODULE_USER;
1009     control->private_data = snd_malloc(info->count * sizeof(unsigned long));
1010     if (!control->private_data) {
1011         snd_err("no memory\n");
1012         goto err;
1013     }
1014     if (info->private_data) {
1015         memcpy(control->private_data, info->private_data, info->count * sizeof(unsigned long));
1016     } else {
1017         unsigned long *user_value;
1018         int i;
1019         user_value = (unsigned long *)control->private_data;
1020         for (i = 0; i < info->count; i++)
1021             user_value[i] = info->value;
1022     }
1023     control->count = info->count;
1024     control->max = info->max;
1025     control->min = info->min;
1026 #if 0
1027     control->mask = ((1 << __fls(control->max)) - 1);
1028 #else
1029     control->mask = 0;
1030 #endif
1031     control->id = ctl->controls_num++;
1032     control->get = snd_ctl_kcontrol_user_get;
1033     control->set = snd_ctl_kcontrol_user_set;
1034 
1035     list_add_tail(&control->list, &ctl->controls);
1036     return 0;
1037 err:
1038     if (control->private_data)
1039         snd_free(control->private_data);
1040     if (control->name)
1041         snd_free(control->name);
1042     if (control)
1043         snd_free(control);
1044     return -1;
1045 }
1046 
snd_ctl_create(struct snd_card * card)1047 static int snd_ctl_create(struct snd_card *card)
1048 {
1049     struct snd_ctl *ctl;
1050     int ret;
1051 
1052     snd_print("\n");
1053     ctl = snd_malloc(sizeof(struct snd_ctl));
1054     if (!ctl) {
1055         snd_err("no memory\n");
1056         return -ENOMEM;
1057     }
1058     INIT_LIST_HEAD(&ctl->controls);
1059     ctl->card = card;
1060     snprintf(ctl->id, sizeof(ctl->id), "CTL %s", card->codec->codec_dai->name);
1061     ctl->ctl_mutex = snd_mutex_init();
1062     ret = snd_ctl_add_controls(card, ctl);
1063     if (ret != 0) {
1064         snd_free(ctl);
1065         return ret;
1066     }
1067 
1068     card->ctl = ctl;
1069     return 0;
1070 }
1071 
snd_pcm_new(struct snd_card * card)1072 static int snd_pcm_new(struct snd_card *card)
1073 {
1074     int ret = 0, playback = 0, capture = 0;
1075     struct snd_dai *codec_dai, *cpu_dai;
1076     struct snd_pcm *pcm;
1077 
1078     snd_print("\n");
1079     /* TODO:create multi pcm device according codec_dai & cpu_dai */
1080     codec_dai = card->codec->codec_dai;
1081     cpu_dai = card->platform->cpu_dai;
1082     if (codec_dai->playback.channels_min != 0
1083         && cpu_dai->playback.channels_min != 0)
1084         playback = 1;
1085     if (codec_dai->capture.channels_min != 0
1086         && cpu_dai->capture.channels_min != 0)
1087         capture = 1;
1088     if (card->codec->playback_only)
1089         capture = 0;
1090     if (card->codec->capture_only)
1091         playback = 0;
1092 
1093     pcm = snd_malloc(sizeof(struct snd_pcm));
1094     if (!pcm) {
1095         snd_err("no memory\n");
1096         return -ENOMEM;
1097     }
1098 
1099     INIT_LIST_HEAD(&pcm->list);
1100     pcm->card = card;
1101     pcm->num = 0;
1102     snprintf(pcm->id, sizeof(pcm->id), "PCM %s", codec_dai->name);
1103     ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback);
1104     if (ret != 0) {
1105         snd_err("snd_pcm_new_stream failed\n");
1106         goto err;
1107     }
1108     ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture);
1109     if (ret != 0) {
1110         snd_err("snd_pcm_new_stream failed\n");
1111         goto err;
1112     }
1113 
1114 
1115     if (card->platform->pcm_new) {
1116         ret = card->platform->pcm_new(pcm);
1117         if (ret != 0) {
1118             snd_err("platform pcm_new failed\n");
1119             goto err;
1120         }
1121     }
1122     pcm->private_free = card->platform->pcm_free;
1123     pcm->open_mutex = snd_mutex_init();
1124     list_add(&pcm->list, &card->devices);
1125 
1126     snd_print("snd pcm device create finish, return %d\n", ret);
1127     return ret;
1128 err:
1129     if (pcm != NULL) {
1130         if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK])
1131             snd_pcm_free_stream(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]);
1132         if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE])
1133             snd_pcm_free_stream(pcm->streams[SNDRV_PCM_STREAM_CAPTURE]);
1134         snd_free(pcm);
1135     }
1136     return ret;
1137 }
1138 
snd_card_init(struct snd_card * card)1139 static int snd_card_init(struct snd_card *card)
1140 {
1141     int ret;
1142 
1143     snd_print("\n");
1144 
1145     /* create ctl device */
1146     ret = snd_ctl_create(card);
1147     if (ret < 0) {
1148         snd_err("snd_ctl_create failed, return %d\n", ret);
1149         return ret;
1150     }
1151     /* create pcm device */
1152     ret = snd_pcm_new(card);
1153     if (ret < 0) {
1154         snd_err("snd_pcm_new failed, return %d\n", ret);
1155         return ret;
1156     }
1157 
1158     return 0;
1159 }
1160 
snd_card_release(struct snd_card * card)1161 static int snd_card_release(struct snd_card *card)
1162 {
1163     struct snd_pcm *p, *temp;
1164 
1165     snd_print("\n");
1166     /* free pcm device */
1167     list_for_each_entry_safe(p, temp, &card->devices, list) {
1168         snd_print("pcm id:%s\n", p->id);
1169         snd_pcm_free(p);
1170     }
1171     list_del_init(&card->devices);
1172 
1173     /* free ctl device */
1174     snd_ctl_free(card);
1175 
1176     return 0;
1177 }
1178 
1179 typedef int (*platform_func_t)(struct snd_platform *, int num);
1180 extern int snd_platform_cpudai_register(struct snd_platform *platform, int arg);
1181 extern int snd_platform_daudio_register(struct snd_platform *platform, int num);
1182 extern int snd_platform_dmic_register(struct snd_platform *platform, int arg);
1183 extern int snd_platform_spdif_register(struct snd_platform *platform, int arg);
1184 
1185 #ifndef CONFIG_SND_PLATFORM_SUNXI_CPUDAI
snd_platform_cpudai_register(struct snd_platform * platform,int arg)1186 int snd_platform_cpudai_register(struct snd_platform *platform, int arg)
1187 {
1188     return -1;
1189 }
1190 #endif
1191 #ifndef CONFIG_SND_PLATFORM_SUNXI_DAUDIO
1192 #ifndef CONFIG_SND_PLATFORM_SUN8IW19_DAUDIO
snd_platform_daudio_register(struct snd_platform * platform,int num)1193 int snd_platform_daudio_register(struct snd_platform *platform, int num)
1194 {
1195     return -1;
1196 }
1197 #endif
1198 #endif
1199 #ifndef CONFIG_SND_PLATFORM_SUNXI_DMIC
snd_platform_dmic_register(struct snd_platform * platform,int arg)1200 int snd_platform_dmic_register(struct snd_platform *platform, int arg)
1201 {
1202     return -1;
1203 }
1204 #endif
1205 #ifndef CONFIG_SND_PLATFORM_SUNXI_SPDIF
snd_platform_spdif_register(struct snd_platform * platform,int arg)1206 int snd_platform_spdif_register(struct snd_platform *platform, int arg)
1207 {
1208     return -1;
1209 }
1210 #endif
1211 
snd_platform_register(int type)1212 static struct snd_platform *snd_platform_register(int type)
1213 {
1214     int ret = -1;
1215     struct snd_platform *platform = NULL;
1216     int arg = 0;
1217 
1218     snd_print(" register type:%d\n", type);
1219 
1220     if (type >= SND_PLATFORM_TYPE_MAX) {
1221         snd_err("platfrom type:%d is not supported.\n", type);
1222         return NULL;
1223     }
1224     platform = snd_malloc(sizeof(struct snd_platform));
1225     if (!platform) {
1226         snd_err("no memory\n");
1227         return NULL;
1228     }
1229     switch (type) {
1230         case SND_PLATFORM_TYPE_CPUDAI:
1231             ret = snd_platform_cpudai_register(platform, arg);
1232             break;
1233         case SND_PLATFORM_TYPE_DAUDIO0:
1234         case SND_PLATFORM_TYPE_DAUDIO1:
1235         case SND_PLATFORM_TYPE_DAUDIO2:
1236         case SND_PLATFORM_TYPE_DAUDIO3:
1237             arg = type - SND_PLATFORM_TYPE_DAUDIO0;
1238             ret = snd_platform_daudio_register(platform, arg);
1239             break;
1240         case SND_PLATFORM_TYPE_DMIC:
1241             ret = snd_platform_dmic_register(platform, arg);
1242             break;
1243         case SND_PLATFORM_TYPE_SPDIF:
1244             ret = snd_platform_spdif_register(platform, arg);
1245             break;
1246         default:
1247             ret = -1;
1248             break;
1249     }
1250 
1251     if (ret != 0) {
1252         snd_err("platform type:%d register failed\n", type);
1253         snd_free(platform);
1254         return NULL;
1255     }
1256     platform->type = type;
1257 
1258     return platform;
1259 }
1260 
snd_platform_unregister(struct snd_platform * platform)1261 static int snd_platform_unregister(struct snd_platform *platform)
1262 {
1263     if (!platform)
1264         return -1;
1265     if (platform->controls)
1266         snd_free(platform->controls);
1267     if (platform->cpu_dai)
1268         snd_free(platform->cpu_dai);
1269     snd_free(platform->name);
1270     snd_free(platform);
1271     return 0;
1272 }
1273 
snd_card_find_pcm(struct snd_card * card,int device_num)1274 struct snd_pcm *snd_card_find_pcm(struct snd_card *card, int device_num)
1275 {
1276     struct snd_pcm *p;
1277 
1278     list_for_each_entry(p, &card->devices, list) {
1279         if (p->num == device_num)
1280             return p;
1281     }
1282     return NULL;
1283 }
1284 
snd_card_find_by_name(const char * name)1285 struct snd_card *snd_card_find_by_name(const char *name)
1286 {
1287     struct snd_card *c;
1288     list_for_each_entry(c, &gCardList, list) {
1289         if (strlen(c->name) == strlen(name) && !strcmp(c->name, name))
1290             return c;
1291     }
1292     return NULL;
1293 }
1294 
snd_card_find_by_platform_type(int type)1295 struct snd_card *snd_card_find_by_platform_type(int type)
1296 {
1297     struct snd_card *c;
1298     list_for_each_entry(c, &gCardList, list) {
1299         if (!c->platform)
1300             continue;
1301         if (c->platform->type == type)
1302             return c;
1303     }
1304     return NULL;
1305 }
1306 
snd_card_find_by_num(int num)1307 struct snd_card *snd_card_find_by_num(int num)
1308 {
1309     struct snd_card *c = NULL;
1310 
1311     list_for_each_entry(c, &gCardList, list) {
1312         if (c->num == num)
1313             return c;
1314     }
1315     return NULL;
1316 }
1317 
snd_card_get_number(void)1318 int snd_card_get_number(void)
1319 {
1320     struct snd_card *c = NULL;
1321     struct list_head *list;
1322 
1323     list = gCardList.next;
1324     if (list == &gCardList)
1325         return 0;
1326     c = container_of(list, struct snd_card, list);
1327     return (c->num + 1);
1328 }
1329 
snd_card_register(const char * name,snd_codec_t * codec,int platform_type)1330 int snd_card_register(const char *name,
1331         snd_codec_t *codec,
1332         int platform_type)
1333 {
1334     int ret = 0;
1335     struct snd_card *card= NULL;
1336     struct snd_platform *platform = NULL;
1337 
1338     snd_print("\n");
1339     if (!codec)
1340         return -1;
1341 
1342     card = snd_card_find_by_name(name);
1343     if (card != NULL) {
1344         snd_err("card:%s already registered\n", name);
1345         return -1;
1346     }
1347     card = snd_card_find_by_platform_type(platform_type);
1348     if (card != NULL) {
1349         snd_err("card:%s already registered with platform type:%d\n",
1350              card->name, platform_type);
1351         return -1;
1352     }
1353 
1354     platform = snd_platform_register(platform_type);
1355     if (!platform) {
1356         snd_err("platform register failed\n");
1357         return -1;
1358     }
1359 
1360     card = snd_malloc(sizeof(struct snd_card));
1361     if (!card) {
1362         snd_err("no memory\n");
1363         ret = -ENOMEM;
1364         goto err1;
1365     }
1366     if (!name)
1367         card->name = strdup("unknown");
1368     else
1369         card->name = strdup(name);
1370 
1371     INIT_LIST_HEAD(&card->devices);
1372     INIT_LIST_HEAD(&card->list);
1373     card->codec = codec;
1374     card->platform = platform;
1375 
1376     /* codec & platform probe */
1377     if (codec->probe) {
1378         ret = codec->probe(codec);
1379         if (ret != 0) {
1380             snd_err("codec[%s] probe failed\n", codec->name);
1381             goto err2;
1382         }
1383     }
1384 
1385     if (codec->codec_dai->probe) {
1386         ret = codec->codec_dai->probe(codec->codec_dai);
1387         if (ret != 0) {
1388             snd_err("codec_dai[%s] probe failed\n", codec->codec_dai->name);
1389             goto err2;
1390         }
1391     }
1392 
1393     if (platform->probe) {
1394         ret = platform->probe(platform);
1395         if (ret != 0) {
1396             snd_err("platform[%s] probe failed\n", platform->name);
1397             goto err2;
1398         }
1399     }
1400 
1401     if (platform->cpu_dai->probe) {
1402         ret = platform->cpu_dai->probe(platform->cpu_dai);
1403         if (ret != 0) {
1404             snd_err("cpu_dai[%s] probe failed\n", platform->cpu_dai->name);
1405             goto err2;
1406         }
1407     }
1408 
1409     /* card initialization */
1410     ret = snd_card_init(card);
1411     if (ret != 0) {
1412         snd_err("card init failed\n");
1413         goto err2;
1414     }
1415 
1416     card->num = snd_card_get_number();
1417     list_add(&card->list, &gCardList);
1418 
1419     snd_print("register card:%s success.\n", name);
1420 
1421     return ret;
1422 err2:
1423     snd_free(card->name);
1424     snd_free(card);
1425 err1:
1426     snd_platform_unregister(platform);
1427     return ret;
1428 }
1429 
snd_card_unregister(struct snd_card * card)1430 int snd_card_unregister(struct snd_card *card)
1431 {
1432     if (!card)
1433         return 0;
1434     list_del(&card->list);
1435     if (card->codec->remove)
1436         card->codec->remove(card->codec);
1437     if (card->platform->remove)
1438         card->platform->remove(card->platform);
1439     snd_card_release(card);
1440     snd_platform_unregister(card->platform);
1441     snd_free(card->name);
1442     snd_free(card);
1443     return 0;
1444 }
1445 
snd_card_unregister_all(void)1446 int snd_card_unregister_all(void)
1447 {
1448     struct snd_card *c = NULL, *temp = NULL;
1449 
1450     list_for_each_entry_safe(c, temp, &gCardList, list) {
1451         snd_print("card name:%s\n", c->name);
1452         snd_card_unregister(c);
1453     }
1454     snd_print("\n");
1455     return 0;
1456 }
1457 
snd_card_list(void)1458 void snd_card_list(void)
1459 {
1460     int i = 0;
1461     int card_num = 0;
1462     struct snd_card *card = NULL;
1463 
1464     snd_print("======== Sound Card List ========\n");
1465     card_num = snd_card_get_number();
1466     if (card_num <= 0) {
1467         snd_print("\tno registered card...\n");
1468         return;
1469     }
1470 
1471     snd_print("%8s%20s\n", "card_num", "card_name");
1472     for (i = 0; i < card_num; i++) {
1473         card = snd_card_find_by_num(i);
1474         if (!card) {
1475             snd_print("card_num:%d not find.\n", i);
1476             return;
1477         }
1478         snd_print("%8d%20s\n", i, card->name);
1479     }
1480     snd_print("\n");
1481 }
1482 
snd_core_version(void)1483 void snd_core_version(void)
1484 {
1485 #ifdef CONFIG_KERNEL_FREERTOS
1486     snd_print("AW-SOUND-CORE version:%s, compiled on: %s %s\n",
1487         SND_CORE_VERSION, __DATE__, __TIME__);
1488 #else
1489     snd_print("AW-SOUND-CORE version:%s\n", SND_CORE_VERSION);
1490 #endif
1491 }
1492