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