aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2014-03-25 17:22:15 -0400
committerMark Brown <broonie@linaro.org>2014-03-25 17:22:15 -0400
commitbad318cd02e7cacb8e93608f050fa001830ad224 (patch)
tree8b47692f96016d7df76da4adb15645e5e1e03ad3
parentc61e9e8c47dd6ed82535e2145954ab3770e3c767 (diff)
parent6a91a17bd7b92b2d2aa9ece85457f52a62fd7708 (diff)
Merge remote-tracking branch 'asoc/topic/simple' into asoc-next
-rw-r--r--Documentation/devicetree/bindings/sound/simple-card.txt42
-rw-r--r--sound/soc/generic/simple-card.c220
2 files changed, 183 insertions, 79 deletions
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt
index 881914b139ca..131aa2ad7f1a 100644
--- a/Documentation/devicetree/bindings/sound/simple-card.txt
+++ b/Documentation/devicetree/bindings/sound/simple-card.txt
@@ -23,6 +23,11 @@ Optional properties:
23 23
24Required subnodes: 24Required subnodes:
25 25
26- simple-audio-card,dai-link : container for the CPU and CODEC sub-nodes
27 This container may be omitted when the
28 card has only one DAI link.
29 See the examples.
30
26- simple-audio-card,cpu : CPU sub-node 31- simple-audio-card,cpu : CPU sub-node
27- simple-audio-card,codec : CODEC sub-node 32- simple-audio-card,codec : CODEC sub-node
28 33
@@ -49,7 +54,7 @@ Note:
49 CPU and CODEC sides as we need to keep the settings identical for both ends 54 CPU and CODEC sides as we need to keep the settings identical for both ends
50 of the link. 55 of the link.
51 56
52Example: 57Example 1 - single DAI link:
53 58
54sound { 59sound {
55 compatible = "simple-audio-card"; 60 compatible = "simple-audio-card";
@@ -94,3 +99,38 @@ sh_fsi2: sh_fsi2@ec230000 {
94 interrupt-parent = <&gic>; 99 interrupt-parent = <&gic>;
95 interrupts = <0 146 0x4>; 100 interrupts = <0 146 0x4>;
96}; 101};
102
103Example 2 - many DAI links:
104
105sound {
106 compatible = "simple-audio-card";
107 simple-audio-card,name = "Cubox Audio";
108 simple-audio-card,format = "i2s";
109
110 simple-audio-card,dai-link@0 { /* I2S - HDMI */
111 simple-audio-card,cpu {
112 sound-dai = <&audio1 0>;
113 };
114 simple-audio-card,codec {
115 sound-dai = <&tda998x 0>;
116 };
117 };
118
119 simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */
120 simple-audio-card,cpu {
121 sound-dai = <&audio1 1>;
122 };
123 simple-audio-card,codec {
124 sound-dai = <&tda998x 1>;
125 };
126 };
127
128 simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */
129 simple-audio-card,cpu {
130 sound-dai = <&audio1 1>;
131 };
132 simple-audio-card,codec {
133 sound-dai = <&spdif_codec>;
134 };
135 };
136};
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 2ee8ed56bcf1..21f1ccbdf582 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -20,9 +20,11 @@
20 20
21struct simple_card_data { 21struct simple_card_data {
22 struct snd_soc_card snd_card; 22 struct snd_soc_card snd_card;
23 struct asoc_simple_dai cpu_dai; 23 struct simple_dai_props {
24 struct asoc_simple_dai codec_dai; 24 struct asoc_simple_dai cpu_dai;
25 struct snd_soc_dai_link snd_link; 25 struct asoc_simple_dai codec_dai;
26 } *dai_props;
27 struct snd_soc_dai_link dai_link[]; /* dynamically allocated */
26}; 28};
27 29
28static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, 30static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
@@ -68,13 +70,16 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
68 snd_soc_card_get_drvdata(rtd->card); 70 snd_soc_card_get_drvdata(rtd->card);
69 struct snd_soc_dai *codec = rtd->codec_dai; 71 struct snd_soc_dai *codec = rtd->codec_dai;
70 struct snd_soc_dai *cpu = rtd->cpu_dai; 72 struct snd_soc_dai *cpu = rtd->cpu_dai;
71 int ret; 73 struct simple_dai_props *dai_props;
74 int num, ret;
72 75
73 ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai); 76 num = rtd - rtd->card->rtd;
77 dai_props = &priv->dai_props[num];
78 ret = __asoc_simple_card_dai_init(codec, &dai_props->codec_dai);
74 if (ret < 0) 79 if (ret < 0)
75 return ret; 80 return ret;
76 81
77 ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai); 82 ret = __asoc_simple_card_dai_init(cpu, &dai_props->cpu_dai);
78 if (ret < 0) 83 if (ret < 0)
79 return ret; 84 return ret;
80 85
@@ -146,13 +151,47 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
146 return 0; 151 return 0;
147} 152}
148 153
154static int simple_card_cpu_codec_of(struct device_node *node,
155 int daifmt,
156 struct snd_soc_dai_link *dai_link,
157 struct simple_dai_props *dai_props)
158{
159 struct device_node *np;
160 int ret;
161
162 /* CPU sub-node */
163 ret = -EINVAL;
164 np = of_get_child_by_name(node, "simple-audio-card,cpu");
165 if (np) {
166 ret = asoc_simple_card_sub_parse_of(np, daifmt,
167 &dai_props->cpu_dai,
168 &dai_link->cpu_of_node,
169 &dai_link->cpu_dai_name);
170 of_node_put(np);
171 }
172 if (ret < 0)
173 return ret;
174
175 /* CODEC sub-node */
176 ret = -EINVAL;
177 np = of_get_child_by_name(node, "simple-audio-card,codec");
178 if (np) {
179 ret = asoc_simple_card_sub_parse_of(np, daifmt,
180 &dai_props->codec_dai,
181 &dai_link->codec_of_node,
182 &dai_link->codec_dai_name);
183 of_node_put(np);
184 }
185 return ret;
186}
187
149static int asoc_simple_card_parse_of(struct device_node *node, 188static int asoc_simple_card_parse_of(struct device_node *node,
150 struct simple_card_data *priv, 189 struct simple_card_data *priv,
151 struct device *dev) 190 struct device *dev,
191 int multi)
152{ 192{
153 struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; 193 struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link;
154 struct asoc_simple_dai *codec_dai = &priv->codec_dai; 194 struct simple_dai_props *dai_props = priv->dai_props;
155 struct asoc_simple_dai *cpu_dai = &priv->cpu_dai;
156 struct device_node *np; 195 struct device_node *np;
157 char *name; 196 char *name;
158 unsigned int daifmt; 197 unsigned int daifmt;
@@ -181,78 +220,71 @@ static int asoc_simple_card_parse_of(struct device_node *node,
181 return ret; 220 return ret;
182 } 221 }
183 222
184 /* CPU sub-node */ 223 /* loop on the DAI links */
185 ret = -EINVAL; 224 np = NULL;
186 np = of_get_child_by_name(node, "simple-audio-card,cpu"); 225 for (;;) {
187 if (np) { 226 if (multi) {
188 ret = asoc_simple_card_sub_parse_of(np, daifmt, 227 np = of_get_next_child(node, np);
189 cpu_dai, 228 if (!np)
190 &dai_link->cpu_of_node, 229 break;
191 &dai_link->cpu_dai_name); 230 }
192 of_node_put(np);
193 }
194 if (ret < 0)
195 return ret;
196 231
197 /* CODEC sub-node */ 232 ret = simple_card_cpu_codec_of(multi ? np : node,
198 ret = -EINVAL; 233 daifmt, dai_link, dai_props);
199 np = of_get_child_by_name(node, "simple-audio-card,codec"); 234 if (ret < 0)
200 if (np) { 235 goto err;
201 ret = asoc_simple_card_sub_parse_of(np, daifmt,
202 codec_dai,
203 &dai_link->codec_of_node,
204 &dai_link->codec_dai_name);
205 of_node_put(np);
206 }
207 if (ret < 0)
208 return ret;
209 236
210 /* 237 /*
211 * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC 238 * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC
212 * while the other bits should be identical unless buggy SW/HW design. 239 * while the other bits should be identical unless buggy SW/HW design.
213 */ 240 */
214 cpu_dai->fmt = codec_dai->fmt; 241 dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt;
242
243 if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
244 ret = -EINVAL;
245 goto err;
246 }
247
248 /* simple-card assumes platform == cpu */
249 dai_link->platform_of_node = dai_link->cpu_of_node;
250
251 name = devm_kzalloc(dev,
252 strlen(dai_link->cpu_dai_name) +
253 strlen(dai_link->codec_dai_name) + 2,
254 GFP_KERNEL);
255 sprintf(name, "%s-%s", dai_link->cpu_dai_name,
256 dai_link->codec_dai_name);
257 dai_link->name = dai_link->stream_name = name;
215 258
216 if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) 259 if (!multi)
217 return -EINVAL; 260 break;
261
262 dai_link++;
263 dai_props++;
264 }
218 265
219 /* card name is created from CPU/CODEC dai name */ 266 /* card name is created from CPU/CODEC dai name */
220 name = devm_kzalloc(dev, 267 dai_link = priv->snd_card.dai_link;
221 strlen(dai_link->cpu_dai_name) +
222 strlen(dai_link->codec_dai_name) + 2,
223 GFP_KERNEL);
224 sprintf(name, "%s-%s", dai_link->cpu_dai_name,
225 dai_link->codec_dai_name);
226 if (!priv->snd_card.name) 268 if (!priv->snd_card.name)
227 priv->snd_card.name = name; 269 priv->snd_card.name = dai_link->name;
228 dai_link->name = dai_link->stream_name = name;
229
230 /* simple-card assumes platform == cpu */
231 dai_link->platform_of_node = dai_link->cpu_of_node;
232 270
233 dev_dbg(dev, "card-name : %s\n", name); 271 dev_dbg(dev, "card-name : %s\n", priv->snd_card.name);
234 dev_dbg(dev, "platform : %04x\n", daifmt); 272 dev_dbg(dev, "platform : %04x\n", daifmt);
273 dai_props = priv->dai_props;
235 dev_dbg(dev, "cpu : %s / %04x / %d\n", 274 dev_dbg(dev, "cpu : %s / %04x / %d\n",
236 dai_link->cpu_dai_name, 275 dai_link->cpu_dai_name,
237 cpu_dai->fmt, 276 dai_props->cpu_dai.fmt,
238 cpu_dai->sysclk); 277 dai_props->cpu_dai.sysclk);
239 dev_dbg(dev, "codec : %s / %04x / %d\n", 278 dev_dbg(dev, "codec : %s / %04x / %d\n",
240 dai_link->codec_dai_name, 279 dai_link->codec_dai_name,
241 codec_dai->fmt, 280 dai_props->codec_dai.fmt,
242 codec_dai->sysclk); 281 dai_props->codec_dai.sysclk);
243
244 /*
245 * soc_bind_dai_link() will check cpu name
246 * after of_node matching if dai_link has cpu_dai_name.
247 * but, it will never match if name was created by fmt_single_name()
248 * remove cpu_dai_name to escape name matching.
249 * see
250 * fmt_single_name()
251 * fmt_multiple_name()
252 */
253 dai_link->cpu_dai_name = NULL;
254 282
255 return 0; 283 return 0;
284
285err:
286 of_node_put(np);
287 return ret;
256} 288}
257 289
258/* update the reference count of the devices nodes at end of probe */ 290/* update the reference count of the devices nodes at end of probe */
@@ -282,9 +314,21 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
282 struct snd_soc_dai_link *dai_link; 314 struct snd_soc_dai_link *dai_link;
283 struct device_node *np = pdev->dev.of_node; 315 struct device_node *np = pdev->dev.of_node;
284 struct device *dev = &pdev->dev; 316 struct device *dev = &pdev->dev;
285 int ret; 317 int num_links, multi, ret;
318
319 /* get the number of DAI links */
320 if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) {
321 num_links = of_get_child_count(np);
322 multi = 1;
323 } else {
324 num_links = 1;
325 multi = 0;
326 }
286 327
287 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 328 /* allocate the private data and the DAI link array */
329 priv = devm_kzalloc(dev,
330 sizeof(*priv) + sizeof(*dai_link) * num_links,
331 GFP_KERNEL);
288 if (!priv) 332 if (!priv)
289 return -ENOMEM; 333 return -ENOMEM;
290 334
@@ -293,18 +337,38 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
293 */ 337 */
294 priv->snd_card.owner = THIS_MODULE; 338 priv->snd_card.owner = THIS_MODULE;
295 priv->snd_card.dev = dev; 339 priv->snd_card.dev = dev;
296 dai_link = &priv->snd_link; 340 dai_link = priv->dai_link;
297 priv->snd_card.dai_link = dai_link; 341 priv->snd_card.dai_link = dai_link;
298 priv->snd_card.num_links = 1; 342 priv->snd_card.num_links = num_links;
343
344 /* get room for the other properties */
345 priv->dai_props = devm_kzalloc(dev,
346 sizeof(*priv->dai_props) * num_links,
347 GFP_KERNEL);
348 if (!priv->dai_props)
349 return -ENOMEM;
299 350
300 if (np && of_device_is_available(np)) { 351 if (np && of_device_is_available(np)) {
301 352
302 ret = asoc_simple_card_parse_of(np, priv, dev); 353 ret = asoc_simple_card_parse_of(np, priv, dev, multi);
303 if (ret < 0) { 354 if (ret < 0) {
304 if (ret != -EPROBE_DEFER) 355 if (ret != -EPROBE_DEFER)
305 dev_err(dev, "parse error %d\n", ret); 356 dev_err(dev, "parse error %d\n", ret);
306 goto err; 357 goto err;
307 } 358 }
359
360 /*
361 * soc_bind_dai_link() will check cpu name
362 * after of_node matching if dai_link has cpu_dai_name.
363 * but, it will never match if name was created by fmt_single_name()
364 * remove cpu_dai_name to escape name matching.
365 * see
366 * fmt_single_name()
367 * fmt_multiple_name()
368 */
369 if (num_links == 1)
370 dai_link->cpu_dai_name = NULL;
371
308 } else { 372 } else {
309 struct asoc_simple_card_info *cinfo; 373 struct asoc_simple_card_info *cinfo;
310 374
@@ -330,13 +394,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
330 dai_link->codec_name = cinfo->codec; 394 dai_link->codec_name = cinfo->codec;
331 dai_link->cpu_dai_name = cinfo->cpu_dai.name; 395 dai_link->cpu_dai_name = cinfo->cpu_dai.name;
332 dai_link->codec_dai_name = cinfo->codec_dai.name; 396 dai_link->codec_dai_name = cinfo->codec_dai.name;
333 memcpy(&priv->cpu_dai, &cinfo->cpu_dai, 397 memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
334 sizeof(priv->cpu_dai)); 398 sizeof(priv->dai_props->cpu_dai));
335 memcpy(&priv->codec_dai, &cinfo->codec_dai, 399 memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai,
336 sizeof(priv->codec_dai)); 400 sizeof(priv->dai_props->codec_dai));
337 401
338 priv->cpu_dai.fmt |= cinfo->daifmt; 402 priv->dai_props->cpu_dai.fmt |= cinfo->daifmt;
339 priv->codec_dai.fmt |= cinfo->daifmt; 403 priv->dai_props->codec_dai.fmt |= cinfo->daifmt;
340 } 404 }
341 405
342 /* 406 /*