diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 86a1e956991e..ba4a3e1897b9 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -56,6 +56,9 @@ struct asoc_simple_priv { struct asoc_simple_dai *dais; struct snd_soc_codec_conf *codec_conf; struct gpio_desc *pa_gpio; + const struct snd_soc_ops *ops; + unsigned int dpcm_selectable:1; + unsigned int force_dpcm:1; }; #define simple_priv_to_card(priv) (&(priv)->snd_card) #define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 0ba50be9ccdb..4db9c0e5445d 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -355,6 +355,11 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, snd_soc_dai_link_set_capabilities(dai_link); dai_link->ops = &graph_ops; + + /* Use custom snd_soc_ops callbacks if available */ + if (priv->ops) + dai_link->ops = priv->ops; + dai_link->init = asoc_simple_dai_init; out_put_node: @@ -439,6 +444,28 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, return 0; } +static inline bool parse_as_dpcm_link(struct asoc_simple_priv *priv, + struct device_node *codec_port, + struct asoc_simple_data *adata) +{ + if (priv->force_dpcm) + return true; + + if (!priv->dpcm_selectable) + return false; + + /* + * It is DPCM + * if Codec port has many endpoints, + * or has convert-xxx property + */ + if ((of_get_child_count(codec_port) > 1) || + (adata->convert_rate || adata->convert_channels)) + return true; + + return false; +} + static int graph_for_each_link(struct asoc_simple_priv *priv, struct link_info *li, int (*func_noml)(struct asoc_simple_priv *priv, @@ -459,7 +486,6 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, struct device_node *codec_port; struct device_node *codec_port_old = NULL; struct asoc_simple_data adata; - uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev); int rc, ret; /* loop for all listed CPU port */ @@ -482,14 +508,8 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, graph_parse_convert(dev, codec_ep, &adata); graph_parse_convert(dev, cpu_ep, &adata); - /* - * It is DPCM - * if Codec port has many endpoints, - * or has convert-xxx property - */ - if (dpcm_selectable && - ((of_get_child_count(codec_port) > 1) || - adata.convert_rate || adata.convert_channels)) + /* check if link requires DPCM parsing */ + if (parse_as_dpcm_link(priv, codec_port, &adata)) ret = func_dpcm(priv, cpu_ep, codec_ep, li, (codec_port_old == codec_port)); /* else normal sound */ @@ -678,6 +698,9 @@ static int graph_probe(struct platform_device *pdev) card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets); card->probe = graph_card_probe; + if (of_device_get_match_data(dev)) + priv->dpcm_selectable = 1; + memset(&li, 0, sizeof(li)); graph_get_dais_count(priv, &li); if (!li.link || !li.dais)