diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index da6353594d61..e5cb602fd248 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -1128,7 +1128,9 @@ int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep, struct device *dev = simple_priv_to_dev(priv); struct device_node *node; struct of_phandle_args args = {}; + struct snd_soc_dai_link_component resolved_dlc = {}; struct snd_soc_dai *dai; + const char *fallback_dai_name; int ret; if (!ep) @@ -1152,39 +1154,31 @@ int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep, dlc->of_node = node; dlc->dai_name = dai_name; dlc->dai_args = dai_args; + } else { + /* Get dai->name */ + args.np = node; + args.args[0] = graph_get_dai_id(ep); + args.args_count = (of_graph_get_endpoint_count(node) > 1); - goto parse_dai_end; + ret = snd_soc_get_dlc(&args, &resolved_dlc); + if (ret < 0) + goto err; + + /* Keep fallback dai_name valid across component rebind */ + fallback_dai_name = resolved_dlc.dai_name; + if (fallback_dai_name) { + fallback_dai_name = devm_kstrdup_const(dev, fallback_dai_name, + GFP_KERNEL); + ret = -ENOMEM; + if (!fallback_dai_name) + goto err; + } + + dlc->of_node = resolved_dlc.of_node; + dlc->dai_name = fallback_dai_name; + dlc->dai_args = resolved_dlc.dai_args; } - /* Get dai->name */ - args.np = node; - args.args[0] = graph_get_dai_id(ep); - args.args_count = (of_graph_get_endpoint_count(node) > 1); - - /* - * FIXME - * - * Here, dlc->dai_name is pointer to CPU/Codec DAI name. - * If user unbinded CPU or Codec driver, but not for Sound Card, - * dlc->dai_name is keeping unbinded CPU or Codec - * driver's pointer. - * - * If user re-bind CPU or Codec driver again, ALSA SoC will try - * to rebind Card via snd_soc_try_rebind_card(), but because of - * above reason, it might can't bind Sound Card. - * Because Sound Card is pointing to released dai_name pointer. - * - * To avoid this rebind Card issue, - * 1) It needs to alloc memory to keep dai_name eventhough - * CPU or Codec driver was unbinded, or - * 2) user need to rebind Sound Card everytime - * if he unbinded CPU or Codec. - */ - ret = snd_soc_get_dlc(&args, dlc); - if (ret < 0) - goto err; - -parse_dai_end: if (is_single_link) *is_single_link = of_graph_get_endpoint_count(node) == 1; ret = 0; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9937a991846e..b24ba1330896 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -69,7 +69,9 @@ static int simple_parse_dai(struct simple_util_priv *priv, { struct device *dev = simple_priv_to_dev(priv); struct of_phandle_args args; + struct snd_soc_dai_link_component resolved_dlc = {}; struct snd_soc_dai *dai; + const char *fallback_dai_name; int ret; if (!node) @@ -94,34 +96,28 @@ static int simple_parse_dai(struct simple_util_priv *priv, dlc->dai_args = snd_soc_copy_dai_args(dev, &args); if (!dlc->dai_args) goto end; + } else { + ret = snd_soc_get_dlc(&args, &resolved_dlc); + if (ret < 0) + goto end; - goto parse_dai_end; + /* Keep fallback dai_name valid across component rebind */ + fallback_dai_name = resolved_dlc.dai_name; + if (fallback_dai_name) { + fallback_dai_name = devm_kstrdup_const(dev, fallback_dai_name, + GFP_KERNEL); + ret = -ENOMEM; + if (!fallback_dai_name) { + of_node_put(resolved_dlc.of_node); + goto end; + } + } + + dlc->of_node = resolved_dlc.of_node; + dlc->dai_name = fallback_dai_name; + dlc->dai_args = resolved_dlc.dai_args; } - /* - * FIXME - * - * Here, dlc->dai_name is pointer to CPU/Codec DAI name. - * If user unbinded CPU or Codec driver, but not for Sound Card, - * dlc->dai_name is keeping unbinded CPU or Codec - * driver's pointer. - * - * If user re-bind CPU or Codec driver again, ALSA SoC will try - * to rebind Card via snd_soc_try_rebind_card(), but because of - * above reason, it might can't bind Sound Card. - * Because Sound Card is pointing to released dai_name pointer. - * - * To avoid this rebind Card issue, - * 1) It needs to alloc memory to keep dai_name eventhough - * CPU or Codec driver was unbinded, or - * 2) user need to rebind Sound Card everytime - * if he unbinded CPU or Codec. - */ - ret = snd_soc_get_dlc(&args, dlc); - if (ret < 0) - goto end; - -parse_dai_end: if (is_single_link) *is_single_link = !args.args_count; ret = 0;