Linux Audio

Check our new training course

Linux BSP development engineering services

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