diff options
author | Rohit kumar <rohitkr@codeaurora.org> | 2018-08-01 05:01:08 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-08-01 07:00:21 -0400 |
commit | c25e295cd77b37903ddc9ee27384e17aad08f27c (patch) | |
tree | 493a58b8725c8eac47de4b9d82a43fd877a82065 /sound | |
parent | 0c901e8cea15ba1e318d8f4342f7dc27a80b5978 (diff) |
ASoC: qcom: Add support to parse common audio device nodes
This adds support to parse cpu, platform and codec
device nodes and add them in dai-links. Also, update
apq8096 machine driver to use the common API.
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Rohit kumar <rohitkr@codeaurora.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/qcom/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/qcom/apq8096.c | 111 | ||||
-rw-r--r-- | sound/soc/qcom/common.c | 112 | ||||
-rw-r--r-- | sound/soc/qcom/common.h | 12 |
4 files changed, 136 insertions, 101 deletions
diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index 206945bb9ba1..fefecc072265 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile | |||
@@ -13,7 +13,7 @@ obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o | |||
13 | # Machine | 13 | # Machine |
14 | snd-soc-storm-objs := storm.o | 14 | snd-soc-storm-objs := storm.o |
15 | snd-soc-apq8016-sbc-objs := apq8016_sbc.o | 15 | snd-soc-apq8016-sbc-objs := apq8016_sbc.o |
16 | snd-soc-apq8096-objs := apq8096.o | 16 | snd-soc-apq8096-objs := apq8096.o common.o |
17 | 17 | ||
18 | obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o | 18 | obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o |
19 | obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o | 19 | obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o |
diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c index a56156281c8d..1e4a90d59228 100644 --- a/sound/soc/qcom/apq8096.c +++ b/sound/soc/qcom/apq8096.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <sound/soc.h> | 9 | #include <sound/soc.h> |
10 | #include <sound/soc-dapm.h> | 10 | #include <sound/soc-dapm.h> |
11 | #include <sound/pcm.h> | 11 | #include <sound/pcm.h> |
12 | #include "common.h" | ||
12 | 13 | ||
13 | static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | 14 | static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, |
14 | struct snd_pcm_hw_params *params) | 15 | struct snd_pcm_hw_params *params) |
@@ -24,109 +25,16 @@ static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | |||
24 | return 0; | 25 | return 0; |
25 | } | 26 | } |
26 | 27 | ||
27 | static int apq8096_sbc_parse_of(struct snd_soc_card *card) | 28 | static void apq8096_add_be_ops(struct snd_soc_card *card) |
28 | { | 29 | { |
29 | struct device_node *np; | 30 | struct snd_soc_dai_link *link = card->dai_link; |
30 | struct device_node *codec = NULL; | 31 | int i, num_links = card->num_links; |
31 | struct device_node *platform = NULL; | ||
32 | struct device_node *cpu = NULL; | ||
33 | struct device *dev = card->dev; | ||
34 | struct snd_soc_dai_link *link; | ||
35 | int ret, num_links; | ||
36 | |||
37 | ret = snd_soc_of_parse_card_name(card, "qcom,model"); | ||
38 | if (ret) { | ||
39 | dev_err(dev, "Error parsing card name: %d\n", ret); | ||
40 | return ret; | ||
41 | } | ||
42 | |||
43 | /* DAPM routes */ | ||
44 | if (of_property_read_bool(dev->of_node, "qcom,audio-routing")) { | ||
45 | ret = snd_soc_of_parse_audio_routing(card, | ||
46 | "qcom,audio-routing"); | ||
47 | if (ret) | ||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | /* Populate links */ | ||
52 | num_links = of_get_child_count(dev->of_node); | ||
53 | |||
54 | /* Allocate the DAI link array */ | ||
55 | card->dai_link = kcalloc(num_links, sizeof(*link), GFP_KERNEL); | ||
56 | if (!card->dai_link) | ||
57 | return -ENOMEM; | ||
58 | 32 | ||
59 | card->num_links = num_links; | 33 | for (i = 0; i < num_links; i++) { |
60 | link = card->dai_link; | 34 | if (link->no_pcm == 1) |
61 | |||
62 | for_each_child_of_node(dev->of_node, np) { | ||
63 | cpu = of_get_child_by_name(np, "cpu"); | ||
64 | if (!cpu) { | ||
65 | dev_err(dev, "Can't find cpu DT node\n"); | ||
66 | ret = -EINVAL; | ||
67 | goto err; | ||
68 | } | ||
69 | |||
70 | link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0); | ||
71 | if (!link->cpu_of_node) { | ||
72 | dev_err(card->dev, "error getting cpu phandle\n"); | ||
73 | ret = -EINVAL; | ||
74 | goto err; | ||
75 | } | ||
76 | |||
77 | ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name); | ||
78 | if (ret) { | ||
79 | dev_err(card->dev, "error getting cpu dai name\n"); | ||
80 | goto err; | ||
81 | } | ||
82 | |||
83 | platform = of_get_child_by_name(np, "platform"); | ||
84 | codec = of_get_child_by_name(np, "codec"); | ||
85 | if (codec && platform) { | ||
86 | link->platform_of_node = of_parse_phandle(platform, | ||
87 | "sound-dai", | ||
88 | 0); | ||
89 | if (!link->platform_of_node) { | ||
90 | dev_err(card->dev, "platform dai not found\n"); | ||
91 | ret = -EINVAL; | ||
92 | goto err; | ||
93 | } | ||
94 | |||
95 | ret = snd_soc_of_get_dai_link_codecs(dev, codec, link); | ||
96 | if (ret < 0) { | ||
97 | dev_err(card->dev, "codec dai not found\n"); | ||
98 | goto err; | ||
99 | } | ||
100 | link->no_pcm = 1; | ||
101 | link->ignore_pmdown_time = 1; | ||
102 | link->be_hw_params_fixup = apq8096_be_hw_params_fixup; | 35 | link->be_hw_params_fixup = apq8096_be_hw_params_fixup; |
103 | } else { | ||
104 | link->platform_of_node = link->cpu_of_node; | ||
105 | link->codec_dai_name = "snd-soc-dummy-dai"; | ||
106 | link->codec_name = "snd-soc-dummy"; | ||
107 | link->dynamic = 1; | ||
108 | } | ||
109 | |||
110 | link->ignore_suspend = 1; | ||
111 | ret = of_property_read_string(np, "link-name", &link->name); | ||
112 | if (ret) { | ||
113 | dev_err(card->dev, "error getting codec dai_link name\n"); | ||
114 | goto err; | ||
115 | } | ||
116 | |||
117 | link->dpcm_playback = 1; | ||
118 | link->dpcm_capture = 1; | ||
119 | link->stream_name = link->name; | ||
120 | link++; | 36 | link++; |
121 | } | 37 | } |
122 | |||
123 | return 0; | ||
124 | err: | ||
125 | of_node_put(cpu); | ||
126 | of_node_put(codec); | ||
127 | of_node_put(platform); | ||
128 | kfree(card->dai_link); | ||
129 | return ret; | ||
130 | } | 38 | } |
131 | 39 | ||
132 | static int apq8096_platform_probe(struct platform_device *pdev) | 40 | static int apq8096_platform_probe(struct platform_device *pdev) |
@@ -142,18 +50,21 @@ static int apq8096_platform_probe(struct platform_device *pdev) | |||
142 | card->dev = dev; | 50 | card->dev = dev; |
143 | card->auto_bind = true; | 51 | card->auto_bind = true; |
144 | dev_set_drvdata(dev, card); | 52 | dev_set_drvdata(dev, card); |
145 | ret = apq8096_sbc_parse_of(card); | 53 | ret = qcom_snd_parse_of(card); |
146 | if (ret) { | 54 | if (ret) { |
147 | dev_err(dev, "Error parsing OF data\n"); | 55 | dev_err(dev, "Error parsing OF data\n"); |
148 | goto err; | 56 | goto err; |
149 | } | 57 | } |
150 | 58 | ||
59 | apq8096_add_be_ops(card); | ||
151 | ret = snd_soc_register_card(card); | 60 | ret = snd_soc_register_card(card); |
152 | if (ret) | 61 | if (ret) |
153 | goto err; | 62 | goto err_card_register; |
154 | 63 | ||
155 | return 0; | 64 | return 0; |
156 | 65 | ||
66 | err_card_register: | ||
67 | kfree(card->dai_link); | ||
157 | err: | 68 | err: |
158 | kfree(card); | 69 | kfree(card); |
159 | return ret; | 70 | return ret; |
diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c new file mode 100644 index 000000000000..eb1b9da05dd4 --- /dev/null +++ b/sound/soc/qcom/common.c | |||
@@ -0,0 +1,112 @@ | |||
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"); | ||
diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h new file mode 100644 index 000000000000..ad5d2cf27459 --- /dev/null +++ b/sound/soc/qcom/common.h | |||
@@ -0,0 +1,12 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | // Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | |||
4 | #ifndef __QCOM_SND_COMMON_H__ | ||
5 | #define __QCOM_SND_COMMON_H__ | ||
6 | |||
7 | #include <linux/component.h> | ||
8 | #include <sound/soc.h> | ||
9 | |||
10 | int qcom_snd_parse_of(struct snd_soc_card *card); | ||
11 | |||
12 | #endif | ||