2 * ASoC driver for TI DAVINCI EVM platform
4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
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.
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>
26 #include <asm/mach-types.h>
28 #include <linux/edma.h>
30 #include "davinci-pcm.h"
31 #include "davinci-i2s.h"
33 struct snd_soc_card_drvdata_davinci
{
38 static int evm_startup(struct snd_pcm_substream
*substream
)
40 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
41 struct snd_soc_card
*soc_card
= rtd
->card
;
42 struct snd_soc_card_drvdata_davinci
*drvdata
=
43 snd_soc_card_get_drvdata(soc_card
);
46 return clk_prepare_enable(drvdata
->mclk
);
51 static void evm_shutdown(struct snd_pcm_substream
*substream
)
53 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
54 struct snd_soc_card
*soc_card
= rtd
->card
;
55 struct snd_soc_card_drvdata_davinci
*drvdata
=
56 snd_soc_card_get_drvdata(soc_card
);
59 clk_disable_unprepare(drvdata
->mclk
);
62 static int evm_hw_params(struct snd_pcm_substream
*substream
,
63 struct snd_pcm_hw_params
*params
)
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_card
*soc_card
= rtd
->card
;
70 unsigned sysclk
= ((struct snd_soc_card_drvdata_davinci
*)
71 snd_soc_card_get_drvdata(soc_card
))->sysclk
;
73 /* set the codec system clock */
74 ret
= snd_soc_dai_set_sysclk(codec_dai
, 0, sysclk
, SND_SOC_CLOCK_OUT
);
78 /* set the CPU system clock */
79 ret
= snd_soc_dai_set_sysclk(cpu_dai
, 0, sysclk
, SND_SOC_CLOCK_OUT
);
86 static struct snd_soc_ops evm_ops
= {
87 .startup
= evm_startup
,
88 .shutdown
= evm_shutdown
,
89 .hw_params
= evm_hw_params
,
92 /* davinci-evm machine dapm widgets */
93 static const struct snd_soc_dapm_widget aic3x_dapm_widgets
[] = {
94 SND_SOC_DAPM_HP("Headphone Jack", NULL
),
95 SND_SOC_DAPM_LINE("Line Out", NULL
),
96 SND_SOC_DAPM_MIC("Mic Jack", NULL
),
97 SND_SOC_DAPM_LINE("Line In", NULL
),
100 /* davinci-evm machine audio_mapnections to the codec pins */
101 static const struct snd_soc_dapm_route audio_map
[] = {
102 /* Headphone connected to HPLOUT, HPROUT */
103 {"Headphone Jack", NULL
, "HPLOUT"},
104 {"Headphone Jack", NULL
, "HPROUT"},
106 /* Line Out connected to LLOUT, RLOUT */
107 {"Line Out", NULL
, "LLOUT"},
108 {"Line Out", NULL
, "RLOUT"},
110 /* Mic connected to (MIC3L | MIC3R) */
111 {"MIC3L", NULL
, "Mic Bias"},
112 {"MIC3R", NULL
, "Mic Bias"},
113 {"Mic Bias", NULL
, "Mic Jack"},
115 /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
116 {"LINE1L", NULL
, "Line In"},
117 {"LINE2L", NULL
, "Line In"},
118 {"LINE1R", NULL
, "Line In"},
119 {"LINE2R", NULL
, "Line In"},
122 /* Logic for a aic3x as connected on a davinci-evm */
123 static int evm_aic3x_init(struct snd_soc_pcm_runtime
*rtd
)
125 struct snd_soc_card
*card
= rtd
->card
;
126 struct snd_soc_codec
*codec
= rtd
->codec
;
127 struct device_node
*np
= card
->dev
->of_node
;
130 /* Add davinci-evm specific widgets */
131 snd_soc_dapm_new_controls(&card
->dapm
, aic3x_dapm_widgets
,
132 ARRAY_SIZE(aic3x_dapm_widgets
));
135 ret
= snd_soc_of_parse_audio_routing(card
, "ti,audio-routing");
139 /* Set up davinci-evm specific audio path audio_map */
140 snd_soc_dapm_add_routes(&card
->dapm
, audio_map
,
141 ARRAY_SIZE(audio_map
));
145 snd_soc_dapm_nc_pin(&codec
->dapm
, "MONO_LOUT");
146 snd_soc_dapm_nc_pin(&codec
->dapm
, "HPLCOM");
147 snd_soc_dapm_nc_pin(&codec
->dapm
, "HPRCOM");
152 /* davinci-evm digital audio interface glue - connects codec <--> CPU */
153 static struct snd_soc_dai_link dm6446_evm_dai
= {
154 .name
= "TLV320AIC3X",
155 .stream_name
= "AIC3X",
156 .cpu_dai_name
= "davinci-mcbsp",
157 .codec_dai_name
= "tlv320aic3x-hifi",
158 .codec_name
= "tlv320aic3x-codec.1-001b",
159 .platform_name
= "davinci-mcbsp",
160 .init
= evm_aic3x_init
,
162 .dai_fmt
= SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_CBM_CFM
|
163 SND_SOC_DAIFMT_IB_NF
,
166 static struct snd_soc_dai_link dm355_evm_dai
= {
167 .name
= "TLV320AIC3X",
168 .stream_name
= "AIC3X",
169 .cpu_dai_name
= "davinci-mcbsp.1",
170 .codec_dai_name
= "tlv320aic3x-hifi",
171 .codec_name
= "tlv320aic3x-codec.1-001b",
172 .platform_name
= "davinci-mcbsp.1",
173 .init
= evm_aic3x_init
,
175 .dai_fmt
= SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_CBM_CFM
|
176 SND_SOC_DAIFMT_IB_NF
,
179 static struct snd_soc_dai_link dm365_evm_dai
= {
180 #ifdef CONFIG_SND_DM365_AIC3X_CODEC
181 .name
= "TLV320AIC3X",
182 .stream_name
= "AIC3X",
183 .cpu_dai_name
= "davinci-mcbsp",
184 .codec_dai_name
= "tlv320aic3x-hifi",
185 .codec_name
= "tlv320aic3x-codec.1-0018",
186 .platform_name
= "davinci-mcbsp",
187 .init
= evm_aic3x_init
,
189 .dai_fmt
= SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_CBM_CFM
|
190 SND_SOC_DAIFMT_IB_NF
,
191 #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
192 .name
= "Voice Codec - CQ93VC",
193 .stream_name
= "CQ93",
194 .cpu_dai_name
= "davinci-vcif",
195 .codec_dai_name
= "cq93vc-hifi",
196 .codec_name
= "cq93vc-codec",
197 .platform_name
= "davinci-vcif",
201 static struct snd_soc_dai_link dm6467_evm_dai
[] = {
203 .name
= "TLV320AIC3X",
204 .stream_name
= "AIC3X",
205 .cpu_dai_name
= "davinci-mcasp.0",
206 .codec_dai_name
= "tlv320aic3x-hifi",
207 .platform_name
= "davinci-mcasp.0",
208 .codec_name
= "tlv320aic3x-codec.0-001a",
209 .init
= evm_aic3x_init
,
211 .dai_fmt
= SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_CBM_CFM
|
212 SND_SOC_DAIFMT_IB_NF
,
216 .stream_name
= "spdif",
217 .cpu_dai_name
= "davinci-mcasp.1",
218 .codec_dai_name
= "dit-hifi",
219 .codec_name
= "spdif_dit",
220 .platform_name
= "davinci-mcasp.1",
221 .dai_fmt
= SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_CBM_CFM
|
222 SND_SOC_DAIFMT_IB_NF
,
226 static struct snd_soc_dai_link da830_evm_dai
= {
227 .name
= "TLV320AIC3X",
228 .stream_name
= "AIC3X",
229 .cpu_dai_name
= "davinci-mcasp.1",
230 .codec_dai_name
= "tlv320aic3x-hifi",
231 .codec_name
= "tlv320aic3x-codec.1-0018",
232 .platform_name
= "davinci-mcasp.1",
233 .init
= evm_aic3x_init
,
235 .dai_fmt
= SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_CBM_CFM
|
236 SND_SOC_DAIFMT_IB_NF
,
239 static struct snd_soc_dai_link da850_evm_dai
= {
240 .name
= "TLV320AIC3X",
241 .stream_name
= "AIC3X",
242 .cpu_dai_name
= "davinci-mcasp.0",
243 .codec_dai_name
= "tlv320aic3x-hifi",
244 .codec_name
= "tlv320aic3x-codec.1-0018",
245 .platform_name
= "davinci-mcasp.0",
246 .init
= evm_aic3x_init
,
248 .dai_fmt
= SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_CBM_CFM
|
249 SND_SOC_DAIFMT_IB_NF
,
252 /* davinci dm6446 evm audio machine driver */
254 * ASP0 in DM6446 EVM is clocked by U55, as configured by
255 * board-dm644x-evm.c using GPIOs from U18. There are six
256 * options; here we "know" we use a 48 KHz sample rate.
258 static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata
= {
262 static struct snd_soc_card dm6446_snd_soc_card_evm
= {
263 .name
= "DaVinci DM6446 EVM",
264 .owner
= THIS_MODULE
,
265 .dai_link
= &dm6446_evm_dai
,
267 .drvdata
= &dm6446_snd_soc_card_drvdata
,
270 /* davinci dm355 evm audio machine driver */
271 /* ASP1 on DM355 EVM is clocked by an external oscillator */
272 static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata
= {
276 static struct snd_soc_card dm355_snd_soc_card_evm
= {
277 .name
= "DaVinci DM355 EVM",
278 .owner
= THIS_MODULE
,
279 .dai_link
= &dm355_evm_dai
,
281 .drvdata
= &dm355_snd_soc_card_drvdata
,
284 /* davinci dm365 evm audio machine driver */
285 static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata
= {
289 static struct snd_soc_card dm365_snd_soc_card_evm
= {
290 .name
= "DaVinci DM365 EVM",
291 .owner
= THIS_MODULE
,
292 .dai_link
= &dm365_evm_dai
,
294 .drvdata
= &dm365_snd_soc_card_drvdata
,
297 /* davinci dm6467 evm audio machine driver */
298 static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata
= {
302 static struct snd_soc_card dm6467_snd_soc_card_evm
= {
303 .name
= "DaVinci DM6467 EVM",
304 .owner
= THIS_MODULE
,
305 .dai_link
= dm6467_evm_dai
,
306 .num_links
= ARRAY_SIZE(dm6467_evm_dai
),
307 .drvdata
= &dm6467_snd_soc_card_drvdata
,
310 static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata
= {
314 static struct snd_soc_card da830_snd_soc_card
= {
315 .name
= "DA830/OMAP-L137 EVM",
316 .owner
= THIS_MODULE
,
317 .dai_link
= &da830_evm_dai
,
319 .drvdata
= &da830_snd_soc_card_drvdata
,
322 static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata
= {
326 static struct snd_soc_card da850_snd_soc_card
= {
327 .name
= "DA850/OMAP-L138 EVM",
328 .owner
= THIS_MODULE
,
329 .dai_link
= &da850_evm_dai
,
331 .drvdata
= &da850_snd_soc_card_drvdata
,
334 #if defined(CONFIG_OF)
337 * The struct is used as place holder. It will be completely
338 * filled with data from dt node.
340 static struct snd_soc_dai_link evm_dai_tlv320aic3x
= {
341 .name
= "TLV320AIC3X",
342 .stream_name
= "AIC3X",
343 .codec_dai_name
= "tlv320aic3x-hifi",
345 .init
= evm_aic3x_init
,
346 .dai_fmt
= SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_CBM_CFM
|
347 SND_SOC_DAIFMT_IB_NF
,
350 static const struct of_device_id davinci_evm_dt_ids
[] = {
352 .compatible
= "ti,da830-evm-audio",
353 .data
= (void *) &evm_dai_tlv320aic3x
,
357 MODULE_DEVICE_TABLE(of
, davinci_evm_dt_ids
);
359 /* davinci evm audio machine driver */
360 static struct snd_soc_card evm_soc_card
= {
361 .owner
= THIS_MODULE
,
365 static int davinci_evm_probe(struct platform_device
*pdev
)
367 struct device_node
*np
= pdev
->dev
.of_node
;
368 const struct of_device_id
*match
=
369 of_match_device(of_match_ptr(davinci_evm_dt_ids
), &pdev
->dev
);
370 struct snd_soc_dai_link
*dai
= (struct snd_soc_dai_link
*) match
->data
;
371 struct snd_soc_card_drvdata_davinci
*drvdata
= NULL
;
375 evm_soc_card
.dai_link
= dai
;
377 dai
->codec_of_node
= of_parse_phandle(np
, "ti,audio-codec", 0);
378 if (!dai
->codec_of_node
)
381 dai
->cpu_of_node
= of_parse_phandle(np
, "ti,mcasp-controller", 0);
382 if (!dai
->cpu_of_node
)
385 dai
->platform_of_node
= dai
->cpu_of_node
;
387 evm_soc_card
.dev
= &pdev
->dev
;
388 ret
= snd_soc_of_parse_card_name(&evm_soc_card
, "ti,model");
392 mclk
= devm_clk_get(&pdev
->dev
, "mclk");
393 if (PTR_ERR(mclk
) == -EPROBE_DEFER
) {
394 return -EPROBE_DEFER
;
395 } else if (IS_ERR(mclk
)) {
396 dev_dbg(&pdev
->dev
, "mclk not found.\n");
400 drvdata
= devm_kzalloc(&pdev
->dev
, sizeof(*drvdata
), GFP_KERNEL
);
404 drvdata
->mclk
= mclk
;
406 ret
= of_property_read_u32(np
, "ti,codec-clock-rate", &drvdata
->sysclk
);
409 if (!drvdata
->mclk
) {
411 "No clock or clock rate defined.\n");
414 drvdata
->sysclk
= clk_get_rate(drvdata
->mclk
);
415 } else if (drvdata
->mclk
) {
416 unsigned int requestd_rate
= drvdata
->sysclk
;
417 clk_set_rate(drvdata
->mclk
, drvdata
->sysclk
);
418 drvdata
->sysclk
= clk_get_rate(drvdata
->mclk
);
419 if (drvdata
->sysclk
!= requestd_rate
)
421 "Could not get requested rate %u using %u.\n",
422 requestd_rate
, drvdata
->sysclk
);
425 snd_soc_card_set_drvdata(&evm_soc_card
, drvdata
);
426 ret
= devm_snd_soc_register_card(&pdev
->dev
, &evm_soc_card
);
429 dev_err(&pdev
->dev
, "snd_soc_register_card failed (%d)\n", ret
);
434 static int davinci_evm_remove(struct platform_device
*pdev
)
436 struct snd_soc_card
*card
= platform_get_drvdata(pdev
);
438 snd_soc_unregister_card(card
);
443 static struct platform_driver davinci_evm_driver
= {
444 .probe
= davinci_evm_probe
,
445 .remove
= davinci_evm_remove
,
447 .name
= "davinci_evm",
448 .pm
= &snd_soc_pm_ops
,
449 .of_match_table
= of_match_ptr(davinci_evm_dt_ids
),
454 static struct platform_device
*evm_snd_device
;
456 static int __init
evm_init(void)
458 struct snd_soc_card
*evm_snd_dev_data
;
463 * If dtb is there, the devices will be created dynamically.
464 * Only register platfrom driver structure.
466 #if defined(CONFIG_OF)
467 if (of_have_populated_dt())
468 return platform_driver_register(&davinci_evm_driver
);
471 if (machine_is_davinci_evm()) {
472 evm_snd_dev_data
= &dm6446_snd_soc_card_evm
;
474 } else if (machine_is_davinci_dm355_evm()) {
475 evm_snd_dev_data
= &dm355_snd_soc_card_evm
;
477 } else if (machine_is_davinci_dm365_evm()) {
478 evm_snd_dev_data
= &dm365_snd_soc_card_evm
;
480 } else if (machine_is_davinci_dm6467_evm()) {
481 evm_snd_dev_data
= &dm6467_snd_soc_card_evm
;
483 } else if (machine_is_davinci_da830_evm()) {
484 evm_snd_dev_data
= &da830_snd_soc_card
;
486 } else if (machine_is_davinci_da850_evm()) {
487 evm_snd_dev_data
= &da850_snd_soc_card
;
492 evm_snd_device
= platform_device_alloc("soc-audio", index
);
496 platform_set_drvdata(evm_snd_device
, evm_snd_dev_data
);
497 ret
= platform_device_add(evm_snd_device
);
499 platform_device_put(evm_snd_device
);
504 static void __exit
evm_exit(void)
506 #if defined(CONFIG_OF)
507 if (of_have_populated_dt()) {
508 platform_driver_unregister(&davinci_evm_driver
);
513 platform_device_unregister(evm_snd_device
);
516 module_init(evm_init
);
517 module_exit(evm_exit
);
519 MODULE_AUTHOR("Vladimir Barinov");
520 MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
521 MODULE_LICENSE("GPL");