b90fdb8b222079b9f42e58aeb5698ab9f4a56b5a
[openwrt.git] / target / linux / omap / patches-3.12 / 401-ASoC-davinci-evm-Add-device-tree-binding.patch
1 From af9ef849e8700327b807361344427a43c38e823a Mon Sep 17 00:00:00 2001
2 From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
3 Date: Tue, 31 Jul 2012 21:25:38 +0530
4 Subject: [PATCH 212/752] ASoC: davinci-evm: Add device tree binding
5
6 Device tree support for Davinci Machine driver
7
8 When the board boots with device tree, the driver will receive card,
9 codec, dai interface details (like the card name, DAPM routing map,
10 phandle for the audio components described in the dts file, codec mclk
11 speed). The card will be set up based on this information. Since the
12 routing is provided via DT we can mark the card fully routed so core
13 can take care of disconnecting the unused pins.
14
15 Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
16 Signed-off-by: Darren Etheridge <detheridge@ti.com>
17 Signed-off-by: Jyri Sarha <jsarha@ti.com>
18 ---
19  .../bindings/sound/davinci-evm-audio.txt           |   58 ++++++++++
20  sound/soc/davinci/davinci-evm.c                    |  120 +++++++++++++++++++-
21  2 files changed, 176 insertions(+), 2 deletions(-)
22  create mode 100644 Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
23
24 --- /dev/null
25 +++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
26 @@ -0,0 +1,58 @@
27 +* Texas Instruments SoC audio setups with TLV320AIC3X Codec
28 +
29 +Required properties:
30 +- compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx
31 +- ti,model : The user-visible name of this sound complex.
32 +- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
33 +- ti,mcasp-controller : The phandle of the McASP controller
34 +- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
35 +- ti,audio-routing : A list of the connections between audio components.
36 +  Each entry is a pair of strings, the first being the connection's sink,
37 +  the second being the connection's source. Valid names for sources and
38 +  sinks are the codec's pins, and the jacks on the board:
39 +
40 +  TLV320AIC3X pins:
41 +
42 +  * LLOUT
43 +  * RLOUT
44 +  * MONO_LOUT
45 +  * HPLOUT
46 +  * HPROUT
47 +  * HPLCOM
48 +  * HPRCOM
49 +  * MIC3L
50 +  * MIC3R
51 +  * LINE1L
52 +  * LINE2L
53 +  * LINE1R
54 +  * LINE2R
55 +
56 +  Board connectors:
57 +
58 +  * Headphone Jack
59 +  * Line Out
60 +  * Mic Jack
61 +  * Line In
62 +
63 +
64 +Example:
65 +
66 +sound {
67 +       compatible = "ti,da830-evm-audio";
68 +       ti,model = "DA830 EVM";
69 +       ti,audio-codec = <&tlv320aic3x>;
70 +       ti,mcasp-controller = <&mcasp1>;
71 +       ti,codec-clock-rate = <12000000>;
72 +       ti,audio-routing =
73 +               "Headphone Jack",       "HPLOUT",
74 +               "Headphone Jack",       "HPROUT",
75 +               "Line Out",             "LLOUT",
76 +               "Line Out",             "RLOUT",
77 +               "MIC3L",                "Mic Bias 2V",
78 +               "MIC3R",                "Mic Bias 2V",
79 +               "Mic Bias 2V",          "Mic Jack",
80 +               "LINE1L",               "Line In",
81 +               "LINE2L",               "Line In",
82 +               "LINE1R",               "Line In",
83 +               "LINE2R",               "Line In";
84 +};
85 --- a/sound/soc/davinci/davinci-evm.c
86 +++ b/sound/soc/davinci/davinci-evm.c
87 @@ -16,6 +16,7 @@
88  #include <linux/platform_device.h>
89  #include <linux/platform_data/edma.h>
90  #include <linux/i2c.h>
91 +#include <linux/of_platform.h>
92  #include <sound/core.h>
93  #include <sound/pcm.h>
94  #include <sound/soc.h>
95 @@ -23,6 +24,8 @@
96  #include <asm/dma.h>
97  #include <asm/mach-types.h>
98  
99 +#include <linux/edma.h>
100 +
101  #include "davinci-pcm.h"
102  #include "davinci-i2s.h"
103  #include "davinci-mcasp.h"
104 @@ -121,13 +124,22 @@ static int evm_aic3x_init(struct snd_soc
105  {
106         struct snd_soc_codec *codec = rtd->codec;
107         struct snd_soc_dapm_context *dapm = &codec->dapm;
108 +       struct device_node *np = codec->card->dev->of_node;
109 +       int ret;
110  
111         /* Add davinci-evm specific widgets */
112         snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
113                                   ARRAY_SIZE(aic3x_dapm_widgets));
114  
115 -       /* Set up davinci-evm specific audio path audio_map */
116 -       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
117 +       if (np) {
118 +               ret = snd_soc_of_parse_audio_routing(codec->card,
119 +                                                       "ti,audio-routing");
120 +               if (ret)
121 +                       return ret;
122 +       } else {
123 +               /* Set up davinci-evm specific audio path audio_map */
124 +               snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
125 +       }
126  
127         /* not connected */
128         snd_soc_dapm_disable_pin(dapm, "MONO_LOUT");
129 @@ -312,6 +324,98 @@ static struct snd_soc_card da850_snd_soc
130         .drvdata = &da850_snd_soc_card_drvdata,
131  };
132  
133 +#if defined(CONFIG_OF)
134 +
135 +/*
136 + * The struct is used as place holder. It will be completely
137 + * filled with data from dt node.
138 + */
139 +static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
140 +       .name           = "TLV320AIC3X",
141 +       .stream_name    = "AIC3X",
142 +       .codec_dai_name = "tlv320aic3x-hifi",
143 +       .ops            = &evm_ops,
144 +       .init           = evm_aic3x_init,
145 +};
146 +
147 +static const struct of_device_id davinci_evm_dt_ids[] = {
148 +       {
149 +               .compatible = "ti,da830-evm-audio",
150 +               .data = (void *) &evm_dai_tlv320aic3x,
151 +       },
152 +       { /* sentinel */ }
153 +};
154 +MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
155 +
156 +/* davinci evm audio machine driver */
157 +static struct snd_soc_card evm_soc_card = {
158 +       .owner = THIS_MODULE,
159 +       .num_links = 1,
160 +};
161 +
162 +static int davinci_evm_probe(struct platform_device *pdev)
163 +{
164 +       struct device_node *np = pdev->dev.of_node;
165 +       const struct of_device_id *match =
166 +               of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
167 +       struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data;
168 +       struct snd_soc_card_drvdata_davinci *drvdata = NULL;
169 +       int ret = 0;
170 +
171 +       evm_soc_card.dai_link = dai;
172 +
173 +       dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
174 +       if (!dai->codec_of_node)
175 +               return -EINVAL;
176 +
177 +       dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
178 +       if (!dai->cpu_of_node)
179 +               return -EINVAL;
180 +
181 +       dai->platform_of_node = dai->cpu_of_node;
182 +
183 +       evm_soc_card.dev = &pdev->dev;
184 +       ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
185 +       if (ret)
186 +               return ret;
187 +
188 +       drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
189 +       if (!drvdata)
190 +               return -ENOMEM;
191 +
192 +       ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
193 +       if (ret < 0)
194 +               return -EINVAL;
195 +
196 +       snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
197 +       ret = snd_soc_register_card(&evm_soc_card);
198 +
199 +       if (ret)
200 +               dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
201 +
202 +       return ret;
203 +}
204 +
205 +static int davinci_evm_remove(struct platform_device *pdev)
206 +{
207 +       struct snd_soc_card *card = platform_get_drvdata(pdev);
208 +
209 +       snd_soc_unregister_card(card);
210 +
211 +       return 0;
212 +}
213 +
214 +static struct platform_driver davinci_evm_driver = {
215 +       .probe          = davinci_evm_probe,
216 +       .remove         = davinci_evm_remove,
217 +       .driver         = {
218 +               .name   = "davinci_evm",
219 +               .owner  = THIS_MODULE,
220 +               .of_match_table = of_match_ptr(davinci_evm_dt_ids),
221 +       },
222 +};
223 +#endif
224 +
225  static struct platform_device *evm_snd_device;
226  
227  static int __init evm_init(void)
228 @@ -320,6 +424,13 @@ static int __init evm_init(void)
229         int index;
230         int ret;
231  
232 +       /*
233 +        * If dtb is there, the devices will be created dynamically.
234 +        * Only register platfrom driver structure.
235 +        */
236 +       if (of_have_populated_dt())
237 +               return platform_driver_register(&davinci_evm_driver);
238 +
239         if (machine_is_davinci_evm()) {
240                 evm_snd_dev_data = &dm6446_snd_soc_card_evm;
241                 index = 0;
242 @@ -355,6 +466,11 @@ static int __init evm_init(void)
243  
244  static void __exit evm_exit(void)
245  {
246 +       if (of_have_populated_dt()) {
247 +               platform_driver_unregister(&davinci_evm_driver);
248 +               return;
249 +       }
250 +
251         platform_device_unregister(evm_snd_device);
252  }
253