aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2012-07-25 09:09:11 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-08-03 18:03:56 -0400
commit5ef75e710b4950439f953c4897e4a871c2f9dc8f (patch)
treedb66cba26297ae7906882e0ce889a4c88fe186b0
parent0dcd47426abde223b2386165470ec45d9777478e (diff)
ASoC: omap-abe-twl6040: Add device tree support
When the board boots with device tree the driver will receive the name of the card, DAPM routing map, phandle for the audio components described in the dts file, mclk speed, and the possibility of detecting the jack detection. The card will be set up based on this information. Since the routing is provided via DT we can mark the card fully routed so core can take care of disconnecting the unused pins. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Reviwed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt91
-rw-r--r--sound/soc/omap/omap-abe-twl6040.c145
2 files changed, 206 insertions, 30 deletions
diff --git a/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
new file mode 100644
index 000000000000..65dec876cb2d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
@@ -0,0 +1,91 @@
1* Texas Instruments OMAP4+ and twl6040 based audio setups
2
3Required properties:
4- compatible: "ti,abe-twl6040"
5- ti,model: Name of the sound card ( for example "SDP4430")
6- ti,mclk-freq: MCLK frequency for HPPLL operation
7- ti,mcpdm: phandle for the McPDM node
8- ti,twl6040: phandle for the twl6040 core node
9- ti,audio-routing: List of connections between audio components.
10 Each entry is a pair of strings, the first being the connection's sink,
11 the second being the connection's source.
12
13Optional properties:
14- ti,dmic: phandle for the OMAP dmic node if the machine have it connected
15- ti,jack_detection: Need to be set to <1> if the board capable to detect jack
16 insertion, removal.
17
18Available audio endpoints for the audio-routing table:
19
20Board connectors:
21 * Headset Stereophone
22 * Earphone Spk
23 * Ext Spk
24 * Line Out
25 * Vibrator
26 * Headset Mic
27 * Main Handset Mic
28 * Sub Handset Mic
29 * Line In
30 * Digital Mic
31
32twl6040 pins:
33 * HSOL
34 * HSOR
35 * EP
36 * HFL
37 * HFR
38 * AUXL
39 * AUXR
40 * VIBRAL
41 * VIBRAR
42 * HSMIC
43 * MAINMIC
44 * SUBMIC
45 * AFML
46 * AFMR
47
48 * Headset Mic Bias
49 * Main Mic Bias
50 * Digital Mic1 Bias
51 * Digital Mic2 Bias
52
53Digital mic pins:
54 * DMic
55
56Example:
57
58sound {
59 compatible = "ti,abe-twl6040";
60 ti,model = "SDP4430";
61
62 ti,jack-detection = <1>;
63 ti,mclk-freq = <38400000>;
64
65 ti,mcpdm = <&mcpdm>;
66 ti,dmic = <&dmic>;
67
68 ti,twl6040 = <&twl6040>;
69
70 /* Audio routing */
71 ti,audio-routing =
72 "Headset Stereophone", "HSOL",
73 "Headset Stereophone", "HSOR",
74 "Earphone Spk", "EP",
75 "Ext Spk", "HFL",
76 "Ext Spk", "HFR",
77 "Line Out", "AUXL",
78 "Line Out", "AUXR",
79 "Vibrator", "VIBRAL",
80 "Vibrator", "VIBRAR",
81 "HSMIC", "Headset Mic",
82 "Headset Mic", "Headset Mic Bias",
83 "MAINMIC", "Main Handset Mic",
84 "Main Handset Mic", "Main Mic Bias",
85 "SUBMIC", "Sub Handset Mic",
86 "Sub Handset Mic", "Main Mic Bias",
87 "AFML", "Line In",
88 "AFMR", "Line In",
89 "DMic", "Digital Mic",
90 "Digital Mic", "Digital Mic1 Bias";
91};
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
index 9d93793d3077..be525dfe9faa 100644
--- a/sound/soc/omap/omap-abe-twl6040.c
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -25,6 +25,7 @@
25#include <linux/mfd/twl6040.h> 25#include <linux/mfd/twl6040.h>
26#include <linux/platform_data/omap-abe-twl6040.h> 26#include <linux/platform_data/omap-abe-twl6040.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/of.h>
28 29
29#include <sound/core.h> 30#include <sound/core.h>
30#include <sound/pcm.h> 31#include <sound/pcm.h>
@@ -43,6 +44,8 @@
43struct abe_twl6040 { 44struct abe_twl6040 {
44 int jack_detection; /* board can detect jack events */ 45 int jack_detection; /* board can detect jack events */
45 int mclk_freq; /* MCLK frequency speed for twl6040 */ 46 int mclk_freq; /* MCLK frequency speed for twl6040 */
47
48 struct platform_device *dmic_codec_dev;
46}; 49};
47 50
48static int omap_abe_hw_params(struct snd_pcm_substream *substream, 51static int omap_abe_hw_params(struct snd_pcm_substream *substream,
@@ -185,17 +188,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
185 int hs_trim; 188 int hs_trim;
186 int ret = 0; 189 int ret = 0;
187 190
188 /* Disable not connected paths if not used */
189 twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
190 twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
191 twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
192 twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
193 twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
194 twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
195 twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
196 twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
197 twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
198
199 /* 191 /*
200 * Configure McPDM offset cancellation based on the HSOTRIM value from 192 * Configure McPDM offset cancellation based on the HSOTRIM value from
201 * twl6040. 193 * twl6040.
@@ -216,6 +208,24 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
216 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); 208 twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
217 } 209 }
218 210
211 /*
212 * NULL pdata means we booted with DT. In this case the routing is
213 * provided and the card is fully routed, no need to mark pins.
214 */
215 if (!pdata)
216 return ret;
217
218 /* Disable not connected paths if not used */
219 twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
220 twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
221 twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
222 twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
223 twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
224 twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
225 twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
226 twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
227 twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
228
219 return ret; 229 return ret;
220} 230}
221 231
@@ -270,52 +280,116 @@ static struct snd_soc_card omap_abe_card = {
270static __devinit int omap_abe_probe(struct platform_device *pdev) 280static __devinit int omap_abe_probe(struct platform_device *pdev)
271{ 281{
272 struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); 282 struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
283 struct device_node *node = pdev->dev.of_node;
273 struct snd_soc_card *card = &omap_abe_card; 284 struct snd_soc_card *card = &omap_abe_card;
274 struct abe_twl6040 *priv; 285 struct abe_twl6040 *priv;
275 int num_links = 0; 286 int num_links = 0;
276 int ret; 287 int ret = 0;
277 288
278 card->dev = &pdev->dev; 289 card->dev = &pdev->dev;
279 290
280 if (!pdata) {
281 dev_err(&pdev->dev, "Missing pdata\n");
282 return -ENODEV;
283 }
284
285 priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); 291 priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL);
286 if (priv == NULL) 292 if (priv == NULL)
287 return -ENOMEM; 293 return -ENOMEM;
288 294
289 if (pdata->card_name) { 295 priv->dmic_codec_dev = ERR_PTR(-EINVAL);
290 card->name = pdata->card_name; 296
297 if (node) {
298 struct device_node *dai_node;
299
300 if (snd_soc_of_parse_card_name(card, "ti,model")) {
301 dev_err(&pdev->dev, "Card name is not provided\n");
302 return -ENODEV;
303 }
304
305 ret = snd_soc_of_parse_audio_routing(card,
306 "ti,audio-routing");
307 if (ret) {
308 dev_err(&pdev->dev,
309 "Error while parsing DAPM routing\n");
310 return ret;
311 }
312
313 dai_node = of_parse_phandle(node, "ti,mcpdm", 0);
314 if (!dai_node) {
315 dev_err(&pdev->dev, "McPDM node is not provided\n");
316 return -EINVAL;
317 }
318 abe_twl6040_dai_links[0].cpu_dai_name = NULL;
319 abe_twl6040_dai_links[0].cpu_of_node = dai_node;
320
321 dai_node = of_parse_phandle(node, "ti,dmic", 0);
322 if (dai_node) {
323 num_links = 2;
324 abe_twl6040_dai_links[1].cpu_dai_name = NULL;
325 abe_twl6040_dai_links[1].cpu_of_node = dai_node;
326
327 priv->dmic_codec_dev = platform_device_register_simple(
328 "dmic-codec", -1, NULL, 0);
329 if (IS_ERR(priv->dmic_codec_dev)) {
330 dev_err(&pdev->dev,
331 "Can't instantiate dmic-codec\n");
332 return PTR_ERR(priv->dmic_codec_dev);
333 }
334 } else {
335 num_links = 1;
336 }
337
338 of_property_read_u32(node, "ti,jack-detection",
339 &priv->jack_detection);
340 of_property_read_u32(node, "ti,mclk-freq",
341 &priv->mclk_freq);
342 if (!priv->mclk_freq) {
343 dev_err(&pdev->dev, "MCLK frequency not provided\n");
344 ret = -EINVAL;
345 goto err_unregister;
346 }
347
348 omap_abe_card.fully_routed = 1;
349 } else if (pdata) {
350 if (pdata->card_name) {
351 card->name = pdata->card_name;
352 } else {
353 dev_err(&pdev->dev, "Card name is not provided\n");
354 return -ENODEV;
355 }
356
357 if (pdata->has_dmic)
358 num_links = 2;
359 else
360 num_links = 1;
361
362 priv->jack_detection = pdata->jack_detection;
363 priv->mclk_freq = pdata->mclk_freq;
291 } else { 364 } else {
292 dev_err(&pdev->dev, "Card name is not provided\n"); 365 dev_err(&pdev->dev, "Missing pdata\n");
293 return -ENODEV; 366 return -ENODEV;
294 } 367 }
295 368
296 priv->jack_detection = pdata->jack_detection;
297 priv->mclk_freq = pdata->mclk_freq;
298
299 369
300 if (!priv->mclk_freq) { 370 if (!priv->mclk_freq) {
301 dev_err(&pdev->dev, "MCLK frequency missing\n"); 371 dev_err(&pdev->dev, "MCLK frequency missing\n");
302 return -ENODEV; 372 ret = -ENODEV;
373 goto err_unregister;
303 } 374 }
304 375
305 if (pdata->has_dmic)
306 num_links = 2;
307 else
308 num_links = 1;
309
310 card->dai_link = abe_twl6040_dai_links; 376 card->dai_link = abe_twl6040_dai_links;
311 card->num_links = num_links; 377 card->num_links = num_links;
312 378
313 snd_soc_card_set_drvdata(card, priv); 379 snd_soc_card_set_drvdata(card, priv);
314 380
315 ret = snd_soc_register_card(card); 381 ret = snd_soc_register_card(card);
316 if (ret) 382 if (ret) {
317 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", 383 dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
318 ret); 384 ret);
385 goto err_unregister;
386 }
387
388 return 0;
389
390err_unregister:
391 if (!IS_ERR(priv->dmic_codec_dev))
392 platform_device_unregister(priv->dmic_codec_dev);
319 393
320 return ret; 394 return ret;
321} 395}
@@ -323,17 +397,28 @@ static __devinit int omap_abe_probe(struct platform_device *pdev)
323static int __devexit omap_abe_remove(struct platform_device *pdev) 397static int __devexit omap_abe_remove(struct platform_device *pdev)
324{ 398{
325 struct snd_soc_card *card = platform_get_drvdata(pdev); 399 struct snd_soc_card *card = platform_get_drvdata(pdev);
400 struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card);
326 401
327 snd_soc_unregister_card(card); 402 snd_soc_unregister_card(card);
328 403
404 if (!IS_ERR(priv->dmic_codec_dev))
405 platform_device_unregister(priv->dmic_codec_dev);
406
329 return 0; 407 return 0;
330} 408}
331 409
410static const struct of_device_id omap_abe_of_match[] = {
411 {.compatible = "ti,abe-twl6040", },
412 { },
413};
414MODULE_DEVICE_TABLE(of, omap_abe_of_match);
415
332static struct platform_driver omap_abe_driver = { 416static struct platform_driver omap_abe_driver = {
333 .driver = { 417 .driver = {
334 .name = "omap-abe-twl6040", 418 .name = "omap-abe-twl6040",
335 .owner = THIS_MODULE, 419 .owner = THIS_MODULE,
336 .pm = &snd_soc_pm_ops, 420 .pm = &snd_soc_pm_ops,
421 .of_match_table = omap_abe_of_match,
337 }, 422 },
338 .probe = omap_abe_probe, 423 .probe = omap_abe_probe,
339 .remove = __devexit_p(omap_abe_remove), 424 .remove = __devexit_p(omap_abe_remove),