^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (c) 2019 BayLibre, SAS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // Author: Jerome Brunet <jbrunet@baylibre.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sound/soc-dai.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "meson-codec-glue.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) static struct snd_soc_dapm_widget *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) meson_codec_glue_get_input(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct snd_soc_dapm_path *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct snd_soc_dapm_widget *in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) snd_soc_dapm_widget_for_each_source_path(w, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) if (!p->connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Check that we still are in the same component */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (snd_soc_dapm_to_component(w->dapm) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) snd_soc_dapm_to_component(p->source->dapm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (p->source->id == snd_soc_dapm_dai_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return p->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) in = meson_codec_glue_get_input(p->source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void meson_codec_glue_input_set_data(struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct meson_codec_glue_input *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) dai->playback_dma_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct meson_codec_glue_input *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) meson_codec_glue_input_get_data(struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return dai->playback_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) EXPORT_SYMBOL_GPL(meson_codec_glue_input_get_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static struct meson_codec_glue_input *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) meson_codec_glue_output_get_input_data(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct snd_soc_dapm_widget *in =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) meson_codec_glue_get_input(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (WARN_ON(!in))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) dai = in->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return meson_codec_glue_input_get_data(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct meson_codec_glue_input *data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) meson_codec_glue_input_get_data(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) data->params.rate_min = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) data->params.rate_max = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) data->params.formats = 1ULL << (__force int) params_format(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) data->params.channels_min = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) data->params.channels_max = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) data->params.sig_bits = dai->driver->playback.sig_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) EXPORT_SYMBOL_GPL(meson_codec_glue_input_hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned int fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct meson_codec_glue_input *data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) meson_codec_glue_input_get_data(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Save the source stream format for the downstream link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) data->fmt = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) EXPORT_SYMBOL_GPL(meson_codec_glue_input_set_fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int meson_codec_glue_output_startup(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct meson_codec_glue_input *in_data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) meson_codec_glue_output_get_input_data(dai->capture_widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!in_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (WARN_ON(!rtd->dai_link->params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) dev_warn(dai->dev, "codec2codec link expected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Replace link params with the input params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) rtd->dai_link->params = &in_data->params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!in_data->fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) EXPORT_SYMBOL_GPL(meson_codec_glue_output_startup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct meson_codec_glue_input *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) data = kzalloc(sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) meson_codec_glue_input_set_data(dai, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct meson_codec_glue_input *data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) meson_codec_glue_input_get_data(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) MODULE_DESCRIPTION("Amlogic Codec Glue Helpers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)