1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2018, Linaro Limited. 3 // Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 5 #include <linux/module.h> 6 #include "common.h" 7 8 int qcom_snd_parse_of(struct snd_soc_card *card) 9 { 10 struct device_node *np; 11 struct device_node *codec = NULL; 12 struct device_node *platform = NULL; 13 struct device_node *cpu = NULL; 14 struct device *dev = card->dev; 15 struct snd_soc_dai_link *link; 16 int ret, num_links; 17 18 ret = snd_soc_of_parse_card_name(card, "model"); 19 if (ret) { 20 dev_err(dev, "Error parsing card name: %d\n", ret); 21 return ret; 22 } 23 24 /* DAPM routes */ 25 if (of_property_read_bool(dev->of_node, "audio-routing")) { 26 ret = snd_soc_of_parse_audio_routing(card, 27 "audio-routing"); 28 if (ret) 29 return ret; 30 } 31 32 /* Populate links */ 33 num_links = of_get_child_count(dev->of_node); 34 35 /* Allocate the DAI link array */ 36 card->dai_link = kcalloc(num_links, sizeof(*link), GFP_KERNEL); 37 if (!card->dai_link) 38 return -ENOMEM; 39 40 card->num_links = num_links; 41 link = card->dai_link; 42 for_each_child_of_node(dev->of_node, np) { 43 cpu = of_get_child_by_name(np, "cpu"); 44 if (!cpu) { 45 dev_err(dev, "Can't find cpu DT node\n"); 46 ret = -EINVAL; 47 goto err; 48 } 49 50 link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); 51 if (!link->cpu_of_node) { 52 dev_err(card->dev, "error getting cpu phandle\n"); 53 ret = -EINVAL; 54 goto err; 55 } 56 57 ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); 58 if (ret) { 59 dev_err(card->dev, "error getting cpu dai name\n"); 60 goto err; 61 } 62 63 platform = of_get_child_by_name(np, "platform"); 64 codec = of_get_child_by_name(np, "codec"); 65 if (codec && platform) { 66 link->platform_of_node = of_parse_phandle(platform, 67 "sound-dai", 68 0); 69 if (!link->platform_of_node) { 70 dev_err(card->dev, "platform dai not found\n"); 71 ret = -EINVAL; 72 goto err; 73 } 74 75 ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); 76 if (ret < 0) { 77 dev_err(card->dev, "codec dai not found\n"); 78 goto err; 79 } 80 link->no_pcm = 1; 81 link->ignore_pmdown_time = 1; 82 } else { 83 link->platform_of_node = link->cpu_of_node; 84 link->codec_dai_name = "snd-soc-dummy-dai"; 85 link->codec_name = "snd-soc-dummy"; 86 link->dynamic = 1; 87 } 88 89 link->ignore_suspend = 1; 90 ret = of_property_read_string(np, "link-name", &link->name); 91 if (ret) { 92 dev_err(card->dev, "error getting codec dai_link name\n"); 93 goto err; 94 } 95 96 link->dpcm_playback = 1; 97 link->dpcm_capture = 1; 98 link->stream_name = link->name; 99 link++; 100 } 101 102 return 0; 103 err: 104 of_node_put(cpu); 105 of_node_put(codec); 106 of_node_put(platform); 107 kfree(card->dai_link); 108 return ret; 109 } 110 EXPORT_SYMBOL(qcom_snd_parse_of); 111 112 MODULE_LICENSE("GPL v2"); 113