@@ -416,7 +416,8 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
const struct snd_soc_pcm_stream *params,
struct snd_soc_dapm_widget *source,
- struct snd_soc_dapm_widget *sink);
+ struct snd_soc_dapm_widget *sink,
+ struct snd_soc_dai_link *dai_link);
/* dapm path setup */
int snd_soc_dapm_new_widgets(struct snd_soc_card *card);
@@ -876,6 +876,9 @@ struct snd_soc_dai_link {
int be_id; /* optional ID for machine driver BE identification */
const struct snd_soc_pcm_stream *params;
+ /* optional params selection for dai links */
+ int (*params_select)(const struct snd_soc_pcm_stream *params,
+ unsigned int *param_index, int event);
unsigned int dai_fmt; /* format to set on init */
@@ -1469,7 +1469,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
capture_w = cpu_dai->capture_widget;
if (play_w && capture_w) {
ret = snd_soc_dapm_new_pcm(card, dai_link->params,
- capture_w, play_w);
+ capture_w, play_w, dai_link);
if (ret != 0) {
dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
play_w->name, capture_w->name, ret);
@@ -1481,7 +1481,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
capture_w = codec_dai->capture_widget;
if (play_w && capture_w) {
ret = snd_soc_dapm_new_pcm(card, dai_link->params,
- capture_w, play_w);
+ capture_w, play_w, dai_link);
if (ret != 0) {
dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n",
play_w->name, capture_w->name, ret);
@@ -3379,10 +3379,12 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_path *source_p, *sink_p;
struct snd_soc_dai *source, *sink;
const struct snd_soc_pcm_stream *config = w->params;
+ struct snd_soc_dai_link *dai_link = w->priv;
struct snd_pcm_substream substream;
struct snd_pcm_hw_params *params = NULL;
u64 fmt;
- int ret;
+ int ret = 0;
+ unsigned int param_index;
if (WARN_ON(!config) ||
WARN_ON(list_empty(&w->sources) || list_empty(&w->sinks)))
@@ -3402,6 +3404,18 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
source = source_p->source->priv;
sink = sink_p->sink->priv;
+ if (dai_link && dai_link->params_select) {
+ ret = dai_link->params_select(config, ¶m_index, event);
+ if (ret < 0) {
+ dev_err(w->dapm->dev,
+ "ASoC: params_select for dai link widget failed %d\n",
+ ret);
+ goto out;
+ }
+ if (param_index > 0)
+ config += param_index;
+ }
+
/* Be a little careful as we don't want to overflow the mask array */
if (config->formats) {
fmt = ffs(config->formats) - 1;
@@ -3485,7 +3499,8 @@ out:
int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
const struct snd_soc_pcm_stream *params,
struct snd_soc_dapm_widget *source,
- struct snd_soc_dapm_widget *sink)
+ struct snd_soc_dapm_widget *sink,
+ struct snd_soc_dai_link *dai_link)
{
struct snd_soc_dapm_route routes[2];
struct snd_soc_dapm_widget template;
@@ -3517,6 +3532,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
}
w->params = params;
+ w->priv = (void *)dai_link;
memset(&routes, 0, sizeof(routes));