soc-pcm.c (5c68005083d620b1499fc81926a514d39ae8b88c) soc-pcm.c (1c943f60e830d0b959c765df09d4c4b254de0481)
1// SPDX-License-Identifier: GPL-2.0+
2//
3// soc-pcm.c -- ALSA SoC PCM
4//
5// Copyright 2005 Wolfson Microelectronics PLC.
6// Copyright 2005 Openedhand Ltd.
7// Copyright (C) 2010 Slimlogic Ltd.
8// Copyright (C) 2010 Texas Instruments Inc.
9//
10// Authors: Liam Girdwood <lrg@ti.com>
11// Mark Brown <broonie@opensource.wolfsonmicro.com>
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/delay.h>
16#include <linux/pinctrl/consumer.h>
1// SPDX-License-Identifier: GPL-2.0+
2//
3// soc-pcm.c -- ALSA SoC PCM
4//
5// Copyright 2005 Wolfson Microelectronics PLC.
6// Copyright 2005 Openedhand Ltd.
7// Copyright (C) 2010 Slimlogic Ltd.
8// Copyright (C) 2010 Texas Instruments Inc.
9//
10// Authors: Liam Girdwood <lrg@ti.com>
11// Mark Brown <broonie@opensource.wolfsonmicro.com>
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/delay.h>
16#include <linux/pinctrl/consumer.h>
17#include <linux/pm_runtime.h>
18#include <linux/slab.h>
19#include <linux/workqueue.h>
20#include <linux/export.h>
21#include <linux/debugfs.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>

--- 2374 unchanged lines hidden (view full) ---

2400 struct snd_soc_pcm_runtime *be = dpcm->be;
2401 struct snd_pcm_substream *be_substream =
2402 snd_soc_dpcm_get_substream(be, stream);
2403
2404 /* is this op for this BE ? */
2405 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
2406 continue;
2407
17#include <linux/slab.h>
18#include <linux/workqueue.h>
19#include <linux/export.h>
20#include <linux/debugfs.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/pcm_params.h>
24#include <sound/soc.h>

--- 2374 unchanged lines hidden (view full) ---

2399 struct snd_soc_pcm_runtime *be = dpcm->be;
2400 struct snd_pcm_substream *be_substream =
2401 snd_soc_dpcm_get_substream(be, stream);
2402
2403 /* is this op for this BE ? */
2404 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
2405 continue;
2406
2408 if (!snd_soc_dpcm_can_be_prepared(fe, be, stream))
2409 continue;
2410
2411 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
2412 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
2413 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
2414 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
2415 continue;
2416
2417 dev_dbg(be->dev, "ASoC: prepare BE %s\n",
2418 be->dai_link->name);

--- 310 unchanged lines hidden (view full) ---

2729open_end:
2730 snd_soc_dpcm_mutex_unlock(fe);
2731 return ret;
2732}
2733
2734static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
2735 int *playback, int *capture)
2736{
2407 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
2408 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
2409 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
2410 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
2411 continue;
2412
2413 dev_dbg(be->dev, "ASoC: prepare BE %s\n",
2414 be->dai_link->name);

--- 310 unchanged lines hidden (view full) ---

2725open_end:
2726 snd_soc_dpcm_mutex_unlock(fe);
2727 return ret;
2728}
2729
2730static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
2731 int *playback, int *capture)
2732{
2733 struct snd_soc_dai_link *dai_link = rtd->dai_link;
2737 struct snd_soc_dai *cpu_dai;
2734 struct snd_soc_dai *cpu_dai;
2735 int has_playback = 0;
2736 int has_capture = 0;
2738 int i;
2739
2737 int i;
2738
2740 if (rtd->dai_link->dynamic && rtd->dai_link->num_cpus > 1) {
2741 dev_err(rtd->dev,
2742 "DPCM doesn't support Multi CPU for Front-Ends yet\n");
2739 if (dai_link->dynamic && dai_link->num_cpus > 1) {
2740 dev_err(rtd->dev, "DPCM doesn't support Multi CPU for Front-Ends yet\n");
2743 return -EINVAL;
2744 }
2745
2741 return -EINVAL;
2742 }
2743
2746 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
2744 if (dai_link->dynamic || dai_link->no_pcm) {
2747 int stream;
2748
2745 int stream;
2746
2749 if (rtd->dai_link->dpcm_playback) {
2747 if (dai_link->dpcm_playback) {
2750 stream = SNDRV_PCM_STREAM_PLAYBACK;
2751
2752 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
2753 if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
2748 stream = SNDRV_PCM_STREAM_PLAYBACK;
2749
2750 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
2751 if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
2754 *playback = 1;
2752 has_playback = 1;
2755 break;
2756 }
2757 }
2753 break;
2754 }
2755 }
2758 if (!*playback) {
2756 if (!has_playback) {
2759 dev_err(rtd->card->dev,
2760 "No CPU DAIs support playback for stream %s\n",
2757 dev_err(rtd->card->dev,
2758 "No CPU DAIs support playback for stream %s\n",
2761 rtd->dai_link->stream_name);
2759 dai_link->stream_name);
2762 return -EINVAL;
2763 }
2764 }
2760 return -EINVAL;
2761 }
2762 }
2765 if (rtd->dai_link->dpcm_capture) {
2763 if (dai_link->dpcm_capture) {
2766 stream = SNDRV_PCM_STREAM_CAPTURE;
2767
2768 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
2769 if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
2764 stream = SNDRV_PCM_STREAM_CAPTURE;
2765
2766 for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
2767 if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
2770 *capture = 1;
2768 has_capture = 1;
2771 break;
2772 }
2773 }
2774
2769 break;
2770 }
2771 }
2772
2775 if (!*capture) {
2773 if (!has_capture) {
2776 dev_err(rtd->card->dev,
2777 "No CPU DAIs support capture for stream %s\n",
2774 dev_err(rtd->card->dev,
2775 "No CPU DAIs support capture for stream %s\n",
2778 rtd->dai_link->stream_name);
2776 dai_link->stream_name);
2779 return -EINVAL;
2780 }
2781 }
2782 } else {
2783 struct snd_soc_dai *codec_dai;
2784
2785 /* Adapt stream for codec2codec links */
2777 return -EINVAL;
2778 }
2779 }
2780 } else {
2781 struct snd_soc_dai *codec_dai;
2782
2783 /* Adapt stream for codec2codec links */
2786 int cpu_capture = rtd->dai_link->c2c_params ?
2787 SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
2788 int cpu_playback = rtd->dai_link->c2c_params ?
2789 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
2784 int cpu_capture = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_CAPTURE);
2785 int cpu_playback = snd_soc_get_stream_cpu(dai_link, SNDRV_PCM_STREAM_PLAYBACK);
2790
2791 for_each_rtd_codec_dais(rtd, i, codec_dai) {
2786
2787 for_each_rtd_codec_dais(rtd, i, codec_dai) {
2792 if (rtd->dai_link->num_cpus == 1) {
2788 if (dai_link->num_cpus == 1) {
2793 cpu_dai = asoc_rtd_to_cpu(rtd, 0);
2789 cpu_dai = asoc_rtd_to_cpu(rtd, 0);
2794 } else if (rtd->dai_link->num_cpus == rtd->dai_link->num_codecs) {
2790 } else if (dai_link->num_cpus == dai_link->num_codecs) {
2795 cpu_dai = asoc_rtd_to_cpu(rtd, i);
2796 } else {
2797 dev_err(rtd->card->dev,
2798 "N cpus to M codecs link is not supported yet\n");
2799 return -EINVAL;
2800 }
2801
2802 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
2803 snd_soc_dai_stream_valid(cpu_dai, cpu_playback))
2791 cpu_dai = asoc_rtd_to_cpu(rtd, i);
2792 } else {
2793 dev_err(rtd->card->dev,
2794 "N cpus to M codecs link is not supported yet\n");
2795 return -EINVAL;
2796 }
2797
2798 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
2799 snd_soc_dai_stream_valid(cpu_dai, cpu_playback))
2804 *playback = 1;
2800 has_playback = 1;
2805 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
2806 snd_soc_dai_stream_valid(cpu_dai, cpu_capture))
2801 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
2802 snd_soc_dai_stream_valid(cpu_dai, cpu_capture))
2807 *capture = 1;
2803 has_capture = 1;
2808 }
2809 }
2810
2804 }
2805 }
2806
2811 if (rtd->dai_link->playback_only) {
2812 *playback = 1;
2813 *capture = 0;
2814 }
2807 if (dai_link->playback_only)
2808 has_capture = 0;
2815
2809
2816 if (rtd->dai_link->capture_only) {
2817 *playback = 0;
2818 *capture = 1;
2810 if (dai_link->capture_only)
2811 has_playback = 0;
2812
2813 if (!has_playback && !has_capture) {
2814 dev_err(rtd->dev, "substream %s has no playback, no capture\n",
2815 dai_link->stream_name);
2816
2817 return -EINVAL;
2819 }
2820
2818 }
2819
2820 *playback = has_playback;
2821 *capture = has_capture;
2822
2821 return 0;
2822}
2823
2824static int soc_create_pcm(struct snd_pcm **pcm,
2825 struct snd_soc_pcm_runtime *rtd,
2826 int playback, int capture, int num)
2827{
2828 char new_name[64];

--- 211 unchanged lines hidden (view full) ---

3040 SND_SOC_DPCM_STATE_PAUSED,
3041 SND_SOC_DPCM_STATE_SUSPEND,
3042 SND_SOC_DPCM_STATE_PREPARE,
3043 };
3044
3045 return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
3046}
3047EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
2823 return 0;
2824}
2825
2826static int soc_create_pcm(struct snd_pcm **pcm,
2827 struct snd_soc_pcm_runtime *rtd,
2828 int playback, int capture, int num)
2829{
2830 char new_name[64];

--- 211 unchanged lines hidden (view full) ---

3042 SND_SOC_DPCM_STATE_PAUSED,
3043 SND_SOC_DPCM_STATE_SUSPEND,
3044 SND_SOC_DPCM_STATE_PREPARE,
3045 };
3046
3047 return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
3048}
3049EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
3048
3049/*
3050 * We can only prepare a BE DAI if any of it's FE are not prepared,
3051 * running or paused for the specified stream direction.
3052 */
3053int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
3054 struct snd_soc_pcm_runtime *be, int stream)
3055{
3056 const enum snd_soc_dpcm_state state[] = {
3057 SND_SOC_DPCM_STATE_START,
3058 SND_SOC_DPCM_STATE_PAUSED,
3059 SND_SOC_DPCM_STATE_PREPARE,
3060 };
3061
3062 return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
3063}
3064EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_prepared);