Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: codec2codec: deal with params when necessary

When there is an event on codec to codec dai_link, we only need to deal
with params if the event is SND_SOC_DAPM_PRE_PMU, when .hw_params() is
called. For the other events, it is useless.

Also, dealing with the codec to codec params just before calling
.hw_params() callbacks give change to either party on the link to alter
params content in .startup(), which might be useful in some cases

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Link: https://lore.kernel.org/r/20190725165949.29699-4-jbrunet@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Jerome Brunet and committed by
Mark Brown
3dcfb397 054d6500

+92 -67
+92 -67
sound/soc/soc-dapm.c
··· 3764 3764 } 3765 3765 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); 3766 3766 3767 - static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, 3768 - struct snd_kcontrol *kcontrol, int event) 3767 + static int 3768 + snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, 3769 + struct snd_pcm_substream *substream) 3769 3770 { 3770 3771 struct snd_soc_dapm_path *path; 3771 3772 struct snd_soc_dai *source, *sink; 3772 - struct snd_soc_pcm_runtime *rtd = w->priv; 3773 - const struct snd_soc_pcm_stream *config; 3774 - struct snd_pcm_substream substream; 3773 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 3775 3774 struct snd_pcm_hw_params *params = NULL; 3776 - struct snd_pcm_runtime *runtime = NULL; 3775 + const struct snd_soc_pcm_stream *config = NULL; 3777 3776 unsigned int fmt; 3778 - int ret = 0; 3777 + int ret; 3779 3778 3779 + params = kzalloc(sizeof(*params), GFP_KERNEL); 3780 + if (!params) 3781 + return -ENOMEM; 3782 + 3783 + substream->stream = SNDRV_PCM_STREAM_CAPTURE; 3784 + snd_soc_dapm_widget_for_each_source_path(w, path) { 3785 + source = path->source->priv; 3786 + 3787 + ret = snd_soc_dai_startup(source, substream); 3788 + if (ret < 0) { 3789 + dev_err(source->dev, 3790 + "ASoC: startup() failed: %d\n", ret); 3791 + goto out; 3792 + } 3793 + source->active++; 3794 + } 3795 + 3796 + substream->stream = SNDRV_PCM_STREAM_PLAYBACK; 3797 + snd_soc_dapm_widget_for_each_sink_path(w, path) { 3798 + sink = path->sink->priv; 3799 + 3800 + ret = snd_soc_dai_startup(sink, substream); 3801 + if (ret < 0) { 3802 + dev_err(sink->dev, 3803 + "ASoC: startup() failed: %d\n", ret); 3804 + goto out; 3805 + } 3806 + sink->active++; 3807 + } 3808 + 3809 + /* 3810 + * Note: getting the config after .startup() gives a chance to 3811 + * either party on the link to alter the configuration if 3812 + * necessary 3813 + */ 3780 3814 config = rtd->dai_link->params + rtd->params_select; 3781 - 3782 - if (WARN_ON(!config) || 3783 - WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || 3784 - list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) 3785 - return -EINVAL; 3815 + if (WARN_ON(!config)) { 3816 + dev_err(w->dapm->dev, "ASoC: link config missing\n"); 3817 + ret = -EINVAL; 3818 + goto out; 3819 + } 3786 3820 3787 3821 /* Be a little careful as we don't want to overflow the mask array */ 3788 3822 if (config->formats) { ··· 3824 3790 } else { 3825 3791 dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n", 3826 3792 config->formats); 3827 - fmt = 0; 3828 - } 3829 3793 3830 - /* Currently very limited parameter selection */ 3831 - params = kzalloc(sizeof(*params), GFP_KERNEL); 3832 - if (!params) { 3833 - ret = -ENOMEM; 3794 + ret = -EINVAL; 3834 3795 goto out; 3835 3796 } 3836 - snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt); 3837 3797 3798 + snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt); 3838 3799 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = 3839 3800 config->rate_min; 3840 3801 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max = 3841 3802 config->rate_max; 3842 - 3843 3803 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min 3844 3804 = config->channels_min; 3845 3805 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max 3846 3806 = config->channels_max; 3807 + 3808 + substream->stream = SNDRV_PCM_STREAM_CAPTURE; 3809 + snd_soc_dapm_widget_for_each_source_path(w, path) { 3810 + source = path->source->priv; 3811 + 3812 + ret = snd_soc_dai_hw_params(source, substream, params); 3813 + if (ret < 0) 3814 + goto out; 3815 + 3816 + dapm_update_dai_unlocked(substream, params, source); 3817 + } 3818 + 3819 + substream->stream = SNDRV_PCM_STREAM_PLAYBACK; 3820 + snd_soc_dapm_widget_for_each_sink_path(w, path) { 3821 + sink = path->sink->priv; 3822 + 3823 + ret = snd_soc_dai_hw_params(sink, substream, params); 3824 + if (ret < 0) 3825 + goto out; 3826 + 3827 + dapm_update_dai_unlocked(substream, params, sink); 3828 + } 3829 + 3830 + out: 3831 + kfree(params); 3832 + return 0; 3833 + } 3834 + 3835 + static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, 3836 + struct snd_kcontrol *kcontrol, int event) 3837 + { 3838 + struct snd_soc_dapm_path *path; 3839 + struct snd_soc_dai *source, *sink; 3840 + struct snd_soc_pcm_runtime *rtd = w->priv; 3841 + struct snd_pcm_substream substream; 3842 + struct snd_pcm_runtime *runtime = NULL; 3843 + int ret = 0; 3844 + 3845 + if (WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) || 3846 + list_empty(&w->edges[SND_SOC_DAPM_DIR_IN]))) 3847 + return -EINVAL; 3847 3848 3848 3849 memset(&substream, 0, sizeof(substream)); 3849 3850 ··· 3893 3824 3894 3825 switch (event) { 3895 3826 case SND_SOC_DAPM_PRE_PMU: 3896 - substream.stream = SNDRV_PCM_STREAM_CAPTURE; 3897 - snd_soc_dapm_widget_for_each_source_path(w, path) { 3898 - source = path->source->priv; 3827 + ret = snd_soc_dai_link_event_pre_pmu(w, &substream); 3828 + if (ret < 0) 3829 + goto out; 3899 3830 3900 - ret = snd_soc_dai_startup(source, &substream); 3901 - if (ret < 0) { 3902 - dev_err(source->dev, 3903 - "ASoC: startup() failed: %d\n", ret); 3904 - goto out; 3905 - } 3906 - source->active++; 3907 - } 3908 - 3909 - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; 3910 - snd_soc_dapm_widget_for_each_sink_path(w, path) { 3911 - sink = path->sink->priv; 3912 - 3913 - ret = snd_soc_dai_startup(sink, &substream); 3914 - if (ret < 0) { 3915 - dev_err(sink->dev, 3916 - "ASoC: startup() failed: %d\n", ret); 3917 - goto out; 3918 - } 3919 - sink->active++; 3920 - } 3921 - 3922 - substream.stream = SNDRV_PCM_STREAM_CAPTURE; 3923 - snd_soc_dapm_widget_for_each_source_path(w, path) { 3924 - source = path->source->priv; 3925 - 3926 - ret = snd_soc_dai_hw_params(source, &substream, params); 3927 - if (ret < 0) 3928 - goto out; 3929 - 3930 - dapm_update_dai_unlocked(&substream, params, source); 3931 - } 3932 - 3933 - substream.stream = SNDRV_PCM_STREAM_PLAYBACK; 3934 - snd_soc_dapm_widget_for_each_sink_path(w, path) { 3935 - sink = path->sink->priv; 3936 - 3937 - ret = snd_soc_dai_hw_params(sink, &substream, params); 3938 - if (ret < 0) 3939 - goto out; 3940 - 3941 - dapm_update_dai_unlocked(&substream, params, sink); 3942 - } 3943 3831 break; 3944 3832 3945 3833 case SND_SOC_DAPM_POST_PMU: ··· 3958 3932 3959 3933 out: 3960 3934 kfree(runtime); 3961 - kfree(params); 3962 3935 return ret; 3963 3936 } 3964 3937