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)
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;
- /* Get dai->name */
- args.np = node;
- args.args[0] = graph_get_dai_id(ep);
- args.args_count = (of_graph_get_endpoint_count(node) > 1);
+ /* 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;
+ }
- /*
- * 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;
+ dlc->of_node = resolved_dlc.of_node;
+ dlc->dai_name = fallback_dai_name;
+ dlc->dai_args = resolved_dlc.dai_args;
+ }
-parse_dai_end:
if (is_single_link)
*is_single_link = of_graph_get_endpoint_count(node) == 1;
ret = 0;
{
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)
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;
+ }
+ }
- /*
- * 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;
+ dlc->of_node = resolved_dlc.of_node;
+ dlc->dai_name = fallback_dai_name;
+ dlc->dai_args = resolved_dlc.dai_args;
+ }
-parse_dai_end:
if (is_single_link)
*is_single_link = !args.args_count;
ret = 0;