Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/sound/soc/davinci/davinci-evm.c

  1 /*
  2  * ASoC driver for TI DAVINCI EVM platform
  3  *
  4  * Author:      Vladimir Barinov, <vbarinov@embeddedalley.com>
  5  * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License version 2 as
  9  * published by the Free Software Foundation.
 10  */
 11 
 12 #include <linux/module.h>
 13 #include <linux/moduleparam.h>
 14 #include <linux/timer.h>
 15 #include <linux/interrupt.h>
 16 #include <linux/platform_device.h>
 17 #include <linux/platform_data/edma.h>
 18 #include <linux/i2c.h>
 19 #include <linux/of_platform.h>
 20 #include <linux/clk.h>
 21 #include <sound/core.h>
 22 #include <sound/pcm.h>
 23 #include <sound/soc.h>
 24 
 25 #include <asm/dma.h>
 26 #include <asm/mach-types.h>
 27 
 28 #include <linux/edma.h>
 29 
 30 #include "davinci-pcm.h"
 31 #include "davinci-i2s.h"
 32 
 33 struct snd_soc_card_drvdata_davinci {
 34         struct clk *mclk;
 35         unsigned sysclk;
 36 };
 37 
 38 static int evm_startup(struct snd_pcm_substream *substream)
 39 {
 40         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 41         struct snd_soc_card *soc_card = rtd->codec->card;
 42         struct snd_soc_card_drvdata_davinci *drvdata =
 43                 snd_soc_card_get_drvdata(soc_card);
 44 
 45         if (drvdata->mclk)
 46                 return clk_prepare_enable(drvdata->mclk);
 47 
 48         return 0;
 49 }
 50 
 51 static void evm_shutdown(struct snd_pcm_substream *substream)
 52 {
 53         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 54         struct snd_soc_card *soc_card = rtd->codec->card;
 55         struct snd_soc_card_drvdata_davinci *drvdata =
 56                 snd_soc_card_get_drvdata(soc_card);
 57 
 58         if (drvdata->mclk)
 59                 clk_disable_unprepare(drvdata->mclk);
 60 }
 61 
 62 static int evm_hw_params(struct snd_pcm_substream *substream,
 63                          struct snd_pcm_hw_params *params)
 64 {
 65         struct snd_soc_pcm_runtime *rtd = substream->private_data;
 66         struct snd_soc_dai *codec_dai = rtd->codec_dai;
 67         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 68         struct snd_soc_codec *codec = rtd->codec;
 69         struct snd_soc_card *soc_card = codec->card;
 70         int ret = 0;
 71         unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
 72                            snd_soc_card_get_drvdata(soc_card))->sysclk;
 73 
 74         /* set the codec system clock */
 75         ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
 76         if (ret < 0)
 77                 return ret;
 78 
 79         /* set the CPU system clock */
 80         ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
 81         if (ret < 0)
 82                 return ret;
 83 
 84         return 0;
 85 }
 86 
 87 static struct snd_soc_ops evm_ops = {
 88         .startup = evm_startup,
 89         .shutdown = evm_shutdown,
 90         .hw_params = evm_hw_params,
 91 };
 92 
 93 /* davinci-evm machine dapm widgets */
 94 static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
 95         SND_SOC_DAPM_HP("Headphone Jack", NULL),
 96         SND_SOC_DAPM_LINE("Line Out", NULL),
 97         SND_SOC_DAPM_MIC("Mic Jack", NULL),
 98         SND_SOC_DAPM_LINE("Line In", NULL),
 99 };
100 
101 /* davinci-evm machine audio_mapnections to the codec pins */
102 static const struct snd_soc_dapm_route audio_map[] = {
103         /* Headphone connected to HPLOUT, HPROUT */
104         {"Headphone Jack", NULL, "HPLOUT"},
105         {"Headphone Jack", NULL, "HPROUT"},
106 
107         /* Line Out connected to LLOUT, RLOUT */
108         {"Line Out", NULL, "LLOUT"},
109         {"Line Out", NULL, "RLOUT"},
110 
111         /* Mic connected to (MIC3L | MIC3R) */
112         {"MIC3L", NULL, "Mic Bias"},
113         {"MIC3R", NULL, "Mic Bias"},
114         {"Mic Bias", NULL, "Mic Jack"},
115 
116         /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
117         {"LINE1L", NULL, "Line In"},
118         {"LINE2L", NULL, "Line In"},
119         {"LINE1R", NULL, "Line In"},
120         {"LINE2R", NULL, "Line In"},
121 };
122 
123 /* Logic for a aic3x as connected on a davinci-evm */
124 static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
125 {
126         struct snd_soc_card *card = rtd->card;
127         struct snd_soc_codec *codec = rtd->codec;
128         struct device_node *np = codec->card->dev->of_node;
129         int ret;
130 
131         /* Add davinci-evm specific widgets */
132         snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets,
133                                   ARRAY_SIZE(aic3x_dapm_widgets));
134 
135         if (np) {
136                 ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing");
137                 if (ret)
138                         return ret;
139         } else {
140                 /* Set up davinci-evm specific audio path audio_map */
141                 snd_soc_dapm_add_routes(&card->dapm, audio_map,
142                                         ARRAY_SIZE(audio_map));
143         }
144 
145         /* not connected */
146         snd_soc_dapm_nc_pin(&codec->dapm, "MONO_LOUT");
147         snd_soc_dapm_nc_pin(&codec->dapm, "HPLCOM");
148         snd_soc_dapm_nc_pin(&codec->dapm, "HPRCOM");
149 
150         return 0;
151 }
152 
153 /* davinci-evm digital audio interface glue - connects codec <--> CPU */
154 static struct snd_soc_dai_link dm6446_evm_dai = {
155         .name = "TLV320AIC3X",
156         .stream_name = "AIC3X",
157         .cpu_dai_name = "davinci-mcbsp",
158         .codec_dai_name = "tlv320aic3x-hifi",
159         .codec_name = "tlv320aic3x-codec.1-001b",
160         .platform_name = "davinci-mcbsp",
161         .init = evm_aic3x_init,
162         .ops = &evm_ops,
163         .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
164                    SND_SOC_DAIFMT_IB_NF,
165 };
166 
167 static struct snd_soc_dai_link dm355_evm_dai = {
168         .name = "TLV320AIC3X",
169         .stream_name = "AIC3X",
170         .cpu_dai_name = "davinci-mcbsp.1",
171         .codec_dai_name = "tlv320aic3x-hifi",
172         .codec_name = "tlv320aic3x-codec.1-001b",
173         .platform_name = "davinci-mcbsp.1",
174         .init = evm_aic3x_init,
175         .ops = &evm_ops,
176         .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
177                    SND_SOC_DAIFMT_IB_NF,
178 };
179 
180 static struct snd_soc_dai_link dm365_evm_dai = {
181 #ifdef CONFIG_SND_DM365_AIC3X_CODEC
182         .name = "TLV320AIC3X",
183         .stream_name = "AIC3X",
184         .cpu_dai_name = "davinci-mcbsp",
185         .codec_dai_name = "tlv320aic3x-hifi",
186         .codec_name = "tlv320aic3x-codec.1-0018",
187         .platform_name = "davinci-mcbsp",
188         .init = evm_aic3x_init,
189         .ops = &evm_ops,
190         .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
191                    SND_SOC_DAIFMT_IB_NF,
192 #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
193         .name = "Voice Codec - CQ93VC",
194         .stream_name = "CQ93",
195         .cpu_dai_name = "davinci-vcif",
196         .codec_dai_name = "cq93vc-hifi",
197         .codec_name = "cq93vc-codec",
198         .platform_name = "davinci-vcif",
199 #endif
200 };
201 
202 static struct snd_soc_dai_link dm6467_evm_dai[] = {
203         {
204                 .name = "TLV320AIC3X",
205                 .stream_name = "AIC3X",
206                 .cpu_dai_name= "davinci-mcasp.0",
207                 .codec_dai_name = "tlv320aic3x-hifi",
208                 .platform_name = "davinci-mcasp.0",
209                 .codec_name = "tlv320aic3x-codec.0-001a",
210                 .init = evm_aic3x_init,
211                 .ops = &evm_ops,
212                 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
213                            SND_SOC_DAIFMT_IB_NF,
214         },
215         {
216                 .name = "McASP",
217                 .stream_name = "spdif",
218                 .cpu_dai_name= "davinci-mcasp.1",
219                 .codec_dai_name = "dit-hifi",
220                 .codec_name = "spdif_dit",
221                 .platform_name = "davinci-mcasp.1",
222                 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
223                            SND_SOC_DAIFMT_IB_NF,
224         },
225 };
226 
227 static struct snd_soc_dai_link da830_evm_dai = {
228         .name = "TLV320AIC3X",
229         .stream_name = "AIC3X",
230         .cpu_dai_name = "davinci-mcasp.1",
231         .codec_dai_name = "tlv320aic3x-hifi",
232         .codec_name = "tlv320aic3x-codec.1-0018",
233         .platform_name = "davinci-mcasp.1",
234         .init = evm_aic3x_init,
235         .ops = &evm_ops,
236         .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
237                    SND_SOC_DAIFMT_IB_NF,
238 };
239 
240 static struct snd_soc_dai_link da850_evm_dai = {
241         .name = "TLV320AIC3X",
242         .stream_name = "AIC3X",
243         .cpu_dai_name= "davinci-mcasp.0",
244         .codec_dai_name = "tlv320aic3x-hifi",
245         .codec_name = "tlv320aic3x-codec.1-0018",
246         .platform_name = "davinci-mcasp.0",
247         .init = evm_aic3x_init,
248         .ops = &evm_ops,
249         .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
250                    SND_SOC_DAIFMT_IB_NF,
251 };
252 
253 /* davinci dm6446 evm audio machine driver */
254 /*
255  * ASP0 in DM6446 EVM is clocked by U55, as configured by
256  * board-dm644x-evm.c using GPIOs from U18.  There are six
257  * options; here we "know" we use a 48 KHz sample rate.
258  */
259 static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
260         .sysclk = 12288000,
261 };
262 
263 static struct snd_soc_card dm6446_snd_soc_card_evm = {
264         .name = "DaVinci DM6446 EVM",
265         .owner = THIS_MODULE,
266         .dai_link = &dm6446_evm_dai,
267         .num_links = 1,
268         .drvdata = &dm6446_snd_soc_card_drvdata,
269 };
270 
271 /* davinci dm355 evm audio machine driver */
272 /* ASP1 on DM355 EVM is clocked by an external oscillator */
273 static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
274         .sysclk = 27000000,
275 };
276 
277 static struct snd_soc_card dm355_snd_soc_card_evm = {
278         .name = "DaVinci DM355 EVM",
279         .owner = THIS_MODULE,
280         .dai_link = &dm355_evm_dai,
281         .num_links = 1,
282         .drvdata = &dm355_snd_soc_card_drvdata,
283 };
284 
285 /* davinci dm365 evm audio machine driver */
286 static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
287         .sysclk = 27000000,
288 };
289 
290 static struct snd_soc_card dm365_snd_soc_card_evm = {
291         .name = "DaVinci DM365 EVM",
292         .owner = THIS_MODULE,
293         .dai_link = &dm365_evm_dai,
294         .num_links = 1,
295         .drvdata = &dm365_snd_soc_card_drvdata,
296 };
297 
298 /* davinci dm6467 evm audio machine driver */
299 static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
300         .sysclk = 27000000,
301 };
302 
303 static struct snd_soc_card dm6467_snd_soc_card_evm = {
304         .name = "DaVinci DM6467 EVM",
305         .owner = THIS_MODULE,
306         .dai_link = dm6467_evm_dai,
307         .num_links = ARRAY_SIZE(dm6467_evm_dai),
308         .drvdata = &dm6467_snd_soc_card_drvdata,
309 };
310 
311 static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
312         .sysclk = 24576000,
313 };
314 
315 static struct snd_soc_card da830_snd_soc_card = {
316         .name = "DA830/OMAP-L137 EVM",
317         .owner = THIS_MODULE,
318         .dai_link = &da830_evm_dai,
319         .num_links = 1,
320         .drvdata = &da830_snd_soc_card_drvdata,
321 };
322 
323 static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
324         .sysclk = 24576000,
325 };
326 
327 static struct snd_soc_card da850_snd_soc_card = {
328         .name = "DA850/OMAP-L138 EVM",
329         .owner = THIS_MODULE,
330         .dai_link = &da850_evm_dai,
331         .num_links = 1,
332         .drvdata = &da850_snd_soc_card_drvdata,
333 };
334 
335 #if defined(CONFIG_OF)
336 
337 /*
338  * The struct is used as place holder. It will be completely
339  * filled with data from dt node.
340  */
341 static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
342         .name           = "TLV320AIC3X",
343         .stream_name    = "AIC3X",
344         .codec_dai_name = "tlv320aic3x-hifi",
345         .ops            = &evm_ops,
346         .init           = evm_aic3x_init,
347         .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
348                    SND_SOC_DAIFMT_IB_NF,
349 };
350 
351 static const struct of_device_id davinci_evm_dt_ids[] = {
352         {
353                 .compatible = "ti,da830-evm-audio",
354                 .data = (void *) &evm_dai_tlv320aic3x,
355         },
356         { /* sentinel */ }
357 };
358 MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
359 
360 /* davinci evm audio machine driver */
361 static struct snd_soc_card evm_soc_card = {
362         .owner = THIS_MODULE,
363         .num_links = 1,
364 };
365 
366 static int davinci_evm_probe(struct platform_device *pdev)
367 {
368         struct device_node *np = pdev->dev.of_node;
369         const struct of_device_id *match =
370                 of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
371         struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data;
372         struct snd_soc_card_drvdata_davinci *drvdata = NULL;
373         struct clk *mclk;
374         int ret = 0;
375 
376         evm_soc_card.dai_link = dai;
377 
378         dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
379         if (!dai->codec_of_node)
380                 return -EINVAL;
381 
382         dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
383         if (!dai->cpu_of_node)
384                 return -EINVAL;
385 
386         dai->platform_of_node = dai->cpu_of_node;
387 
388         evm_soc_card.dev = &pdev->dev;
389         ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
390         if (ret)
391                 return ret;
392 
393         mclk = devm_clk_get(&pdev->dev, "mclk");
394         if (PTR_ERR(mclk) == -EPROBE_DEFER) {
395                 return -EPROBE_DEFER;
396         } else if (IS_ERR(mclk)) {
397                 dev_dbg(&pdev->dev, "mclk not found.\n");
398                 mclk = NULL;
399         }
400 
401         drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
402         if (!drvdata)
403                 return -ENOMEM;
404 
405         drvdata->mclk = mclk;
406 
407         ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
408 
409         if (ret < 0) {
410                 if (!drvdata->mclk) {
411                         dev_err(&pdev->dev,
412                                 "No clock or clock rate defined.\n");
413                         return -EINVAL;
414                 }
415                 drvdata->sysclk = clk_get_rate(drvdata->mclk);
416         } else if (drvdata->mclk) {
417                 unsigned int requestd_rate = drvdata->sysclk;
418                 clk_set_rate(drvdata->mclk, drvdata->sysclk);
419                 drvdata->sysclk = clk_get_rate(drvdata->mclk);
420                 if (drvdata->sysclk != requestd_rate)
421                         dev_warn(&pdev->dev,
422                                  "Could not get requested rate %u using %u.\n",
423                                  requestd_rate, drvdata->sysclk);
424         }
425 
426         snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
427         ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
428 
429         if (ret)
430                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
431 
432         return ret;
433 }
434 
435 static int davinci_evm_remove(struct platform_device *pdev)
436 {
437         struct snd_soc_card *card = platform_get_drvdata(pdev);
438 
439         snd_soc_unregister_card(card);
440 
441         return 0;
442 }
443 
444 static struct platform_driver davinci_evm_driver = {
445         .probe          = davinci_evm_probe,
446         .remove         = davinci_evm_remove,
447         .driver         = {
448                 .name   = "davinci_evm",
449                 .owner  = THIS_MODULE,
450                 .pm     = &snd_soc_pm_ops,
451                 .of_match_table = of_match_ptr(davinci_evm_dt_ids),
452         },
453 };
454 #endif
455 
456 static struct platform_device *evm_snd_device;
457 
458 static int __init evm_init(void)
459 {
460         struct snd_soc_card *evm_snd_dev_data;
461         int index;
462         int ret;
463 
464         /*
465          * If dtb is there, the devices will be created dynamically.
466          * Only register platfrom driver structure.
467          */
468 #if defined(CONFIG_OF)
469         if (of_have_populated_dt())
470                 return platform_driver_register(&davinci_evm_driver);
471 #endif
472 
473         if (machine_is_davinci_evm()) {
474                 evm_snd_dev_data = &dm6446_snd_soc_card_evm;
475                 index = 0;
476         } else if (machine_is_davinci_dm355_evm()) {
477                 evm_snd_dev_data = &dm355_snd_soc_card_evm;
478                 index = 1;
479         } else if (machine_is_davinci_dm365_evm()) {
480                 evm_snd_dev_data = &dm365_snd_soc_card_evm;
481                 index = 0;
482         } else if (machine_is_davinci_dm6467_evm()) {
483                 evm_snd_dev_data = &dm6467_snd_soc_card_evm;
484                 index = 0;
485         } else if (machine_is_davinci_da830_evm()) {
486                 evm_snd_dev_data = &da830_snd_soc_card;
487                 index = 1;
488         } else if (machine_is_davinci_da850_evm()) {
489                 evm_snd_dev_data = &da850_snd_soc_card;
490                 index = 0;
491         } else
492                 return -EINVAL;
493 
494         evm_snd_device = platform_device_alloc("soc-audio", index);
495         if (!evm_snd_device)
496                 return -ENOMEM;
497 
498         platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
499         ret = platform_device_add(evm_snd_device);
500         if (ret)
501                 platform_device_put(evm_snd_device);
502 
503         return ret;
504 }
505 
506 static void __exit evm_exit(void)
507 {
508 #if defined(CONFIG_OF)
509         if (of_have_populated_dt()) {
510                 platform_driver_unregister(&davinci_evm_driver);
511                 return;
512         }
513 #endif
514 
515         platform_device_unregister(evm_snd_device);
516 }
517 
518 module_init(evm_init);
519 module_exit(evm_exit);
520 
521 MODULE_AUTHOR("Vladimir Barinov");
522 MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
523 MODULE_LICENSE("GPL");
524 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us