int asoc_simple_card_parse_graph_dai(struct device_node *ep, struct device_node **dai_of_node, const char **dai_name) { struct device_node *node; struct of_phandle_args args; int ret; if (!ep) return 0; if (!dai_name) return 0; node = of_graph_get_port_parent(ep); /* Get dai->name */ args.np = node; args.args[0] = asoc_simple_card_get_dai_id(ep); args.args_count = (of_graph_get_endpoint_count(node) > 1); ret = snd_soc_get_dai_name(&args, dai_name); if (ret < 0) return ret; *dai_of_node = node; return 0; }
static int tm2_probe(struct platform_device *pdev) { struct device_node *cpu_dai_node[2] = {}; struct device_node *codec_dai_node[2] = {}; const char *cells_name = NULL; struct device *dev = &pdev->dev; struct snd_soc_card *card = &tm2_card; struct tm2_machine_priv *priv; struct of_phandle_args args; int num_codecs, ret, i; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; snd_soc_card_set_drvdata(card, priv); card->dev = dev; priv->gpio_mic_bias = devm_gpiod_get(dev, "mic-bias", GPIOD_OUT_HIGH); if (IS_ERR(priv->gpio_mic_bias)) { dev_err(dev, "Failed to get mic bias gpio\n"); return PTR_ERR(priv->gpio_mic_bias); } ret = snd_soc_of_parse_card_name(card, "model"); if (ret < 0) { dev_err(dev, "Card name is not specified\n"); return ret; } ret = snd_soc_of_parse_audio_routing(card, "samsung,audio-routing"); if (ret < 0) { dev_err(dev, "Audio routing is not specified or invalid\n"); return ret; } card->aux_dev[0].codec_of_node = of_parse_phandle(dev->of_node, "audio-amplifier", 0); if (!card->aux_dev[0].codec_of_node) { dev_err(dev, "audio-amplifier property invalid or missing\n"); return -EINVAL; } num_codecs = of_count_phandle_with_args(dev->of_node, "audio-codec", NULL); /* Skip the HDMI link if not specified in DT */ if (num_codecs > 1) { card->num_links = ARRAY_SIZE(tm2_dai_links); cells_name = "#sound-dai-cells"; } else { card->num_links = ARRAY_SIZE(tm2_dai_links) - 1; } for (i = 0; i < num_codecs; i++) { struct of_phandle_args args; ret = of_parse_phandle_with_args(dev->of_node, "i2s-controller", cells_name, i, &args); if (!args.np) { dev_err(dev, "i2s-controller property parse error: %d\n", i); ret = -EINVAL; goto dai_node_put; } cpu_dai_node[i] = args.np; codec_dai_node[i] = of_parse_phandle(dev->of_node, "audio-codec", i); if (!codec_dai_node[i]) { dev_err(dev, "audio-codec property parse error\n"); ret = -EINVAL; goto dai_node_put; } } /* Initialize WM5110 - I2S and HDMI - I2S1 DAI links */ for (i = 0; i < card->num_links; i++) { unsigned int dai_index = 0; /* WM5110 */ card->dai_link[i].cpu_name = NULL; card->dai_link[i].platform_name = NULL; if (num_codecs > 1 && i == card->num_links - 1) dai_index = 1; /* HDMI */ card->dai_link[i].codec_of_node = codec_dai_node[dai_index]; card->dai_link[i].cpu_of_node = cpu_dai_node[dai_index]; card->dai_link[i].platform_of_node = cpu_dai_node[dai_index]; } if (num_codecs > 1) { /* HDMI DAI link (I2S1) */ i = card->num_links - 1; ret = of_parse_phandle_with_fixed_args(dev->of_node, "audio-codec", 0, 1, &args); if (ret) { dev_err(dev, "audio-codec property parse error\n"); goto dai_node_put; } ret = snd_soc_get_dai_name(&args, &card->dai_link[i].codec_dai_name); if (ret) { dev_err(dev, "Unable to get codec_dai_name\n"); goto dai_node_put; } } ret = devm_snd_soc_register_component(dev, &tm2_component, tm2_ext_dai, ARRAY_SIZE(tm2_ext_dai)); if (ret < 0) { dev_err(dev, "Failed to register component: %d\n", ret); goto dai_node_put; } ret = devm_snd_soc_register_card(dev, card); if (ret < 0) { dev_err(dev, "Failed to register card: %d\n", ret); goto dai_node_put; } dai_node_put: for (i = 0; i < num_codecs; i++) { of_node_put(codec_dai_node[i]); of_node_put(cpu_dai_node[i]); } of_node_put(card->aux_dev[0].codec_of_node); return ret; }