diff options
author | Vladimir Barinov <vbarinov@ru.mvista.com> | 2008-02-18 05:40:22 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:11 -0400 |
commit | 310355c111dbae005269fe3fc39afdd60779bf5d (patch) | |
tree | fc792358843354483f86ef6695c5fe83db91a9da /sound/soc/davinci/davinci-evm.c | |
parent | b40b04ad380ad641e5740486e4b9a56fd32b64cc (diff) |
[ALSA] Davinci ASoC support
Add ASoC support for the TI Davinci SoC and the Davicni-EVM reference board.
It includes:
- ASoC Davinci DMA driver
- ASoC Davinci I2S (Davinci McBSP module based) driver
- ASoC Davinci-EVM reference board
Signed-off-by: Vladimir Barinov <vbarinov@ru.mvista.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/soc/davinci/davinci-evm.c')
-rw-r--r-- | sound/soc/davinci/davinci-evm.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c new file mode 100644 index 000000000000..fcd165240333 --- /dev/null +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * ASoC driver for TI DAVINCI EVM platform | ||
3 | * | ||
4 | * Author: Vladimir Barinov, <vbarinov@ru.mvista.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 <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/soc.h> | ||
20 | #include <sound/soc-dapm.h> | ||
21 | |||
22 | #include <asm/mach-types.h> | ||
23 | #include <asm/dma.h> | ||
24 | #include <asm/arch/hardware.h> | ||
25 | |||
26 | #include "../codecs/tlv320aic3x.h" | ||
27 | #include "davinci-pcm.h" | ||
28 | #include "davinci-i2s.h" | ||
29 | |||
30 | #define EVM_CODEC_CLOCK 22579200 | ||
31 | |||
32 | static int evm_hw_params(struct snd_pcm_substream *substream, | ||
33 | struct snd_pcm_hw_params *params) | ||
34 | { | ||
35 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
36 | struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; | ||
37 | struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; | ||
38 | int ret = 0; | ||
39 | |||
40 | /* set codec DAI configuration */ | ||
41 | ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
42 | SND_SOC_DAIFMT_CBM_CFM); | ||
43 | if (ret < 0) | ||
44 | return ret; | ||
45 | |||
46 | /* set cpu DAI configuration */ | ||
47 | ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM | | ||
48 | SND_SOC_DAIFMT_IB_NF); | ||
49 | if (ret < 0) | ||
50 | return ret; | ||
51 | |||
52 | /* set the codec system clock */ | ||
53 | ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK, | ||
54 | SND_SOC_CLOCK_OUT); | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static struct snd_soc_ops evm_ops = { | ||
62 | .hw_params = evm_hw_params, | ||
63 | }; | ||
64 | |||
65 | /* davinci-evm machine dapm widgets */ | ||
66 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | ||
67 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
68 | SND_SOC_DAPM_LINE("Line Out", NULL), | ||
69 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
70 | SND_SOC_DAPM_LINE("Line In", NULL), | ||
71 | }; | ||
72 | |||
73 | /* davinci-evm machine audio_mapnections to the codec pins */ | ||
74 | static const char *audio_map[][3] = { | ||
75 | /* Headphone connected to HPLOUT, HPROUT */ | ||
76 | {"Headphone Jack", NULL, "HPLOUT"}, | ||
77 | {"Headphone Jack", NULL, "HPROUT"}, | ||
78 | |||
79 | /* Line Out connected to LLOUT, RLOUT */ | ||
80 | {"Line Out", NULL, "LLOUT"}, | ||
81 | {"Line Out", NULL, "RLOUT"}, | ||
82 | |||
83 | /* Mic connected to (MIC3L | MIC3R) */ | ||
84 | {"MIC3L", NULL, "Mic Bias 2V"}, | ||
85 | {"MIC3R", NULL, "Mic Bias 2V"}, | ||
86 | {"Mic Bias 2V", NULL, "Mic Jack"}, | ||
87 | |||
88 | /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */ | ||
89 | {"LINE1L", NULL, "Line In"}, | ||
90 | {"LINE2L", NULL, "Line In"}, | ||
91 | {"LINE1R", NULL, "Line In"}, | ||
92 | {"LINE2R", NULL, "Line In"}, | ||
93 | |||
94 | {NULL, NULL, NULL}, | ||
95 | }; | ||
96 | |||
97 | /* Logic for a aic3x as connected on a davinci-evm */ | ||
98 | static int evm_aic3x_init(struct snd_soc_codec *codec) | ||
99 | { | ||
100 | int i; | ||
101 | |||
102 | /* Add davinci-evm specific widgets */ | ||
103 | for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++) | ||
104 | snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]); | ||
105 | |||
106 | /* Set up davinci-evm specific audio path audio_map */ | ||
107 | for (i = 0; audio_map[i][0] != NULL; i++) | ||
108 | snd_soc_dapm_connect_input(codec, audio_map[i][0], | ||
109 | audio_map[i][1], audio_map[i][2]); | ||
110 | |||
111 | /* not connected */ | ||
112 | snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0); | ||
113 | snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0); | ||
114 | snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0); | ||
115 | |||
116 | /* always connected */ | ||
117 | snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1); | ||
118 | snd_soc_dapm_set_endpoint(codec, "Line Out", 1); | ||
119 | snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1); | ||
120 | snd_soc_dapm_set_endpoint(codec, "Line In", 1); | ||
121 | |||
122 | snd_soc_dapm_sync_endpoints(codec); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | /* davinci-evm digital audio interface glue - connects codec <--> CPU */ | ||
128 | static struct snd_soc_dai_link evm_dai = { | ||
129 | .name = "TLV320AIC3X", | ||
130 | .stream_name = "AIC3X", | ||
131 | .cpu_dai = &davinci_i2s_dai, | ||
132 | .codec_dai = &aic3x_dai, | ||
133 | .init = evm_aic3x_init, | ||
134 | .ops = &evm_ops, | ||
135 | }; | ||
136 | |||
137 | /* davinci-evm audio machine driver */ | ||
138 | static struct snd_soc_machine snd_soc_machine_evm = { | ||
139 | .name = "DaVinci EVM", | ||
140 | .dai_link = &evm_dai, | ||
141 | .num_links = 1, | ||
142 | }; | ||
143 | |||
144 | /* evm audio private data */ | ||
145 | static struct aic3x_setup_data evm_aic3x_setup = { | ||
146 | .i2c_address = 0x1b, | ||
147 | }; | ||
148 | |||
149 | /* evm audio subsystem */ | ||
150 | static struct snd_soc_device evm_snd_devdata = { | ||
151 | .machine = &snd_soc_machine_evm, | ||
152 | .platform = &davinci_soc_platform, | ||
153 | .codec_dev = &soc_codec_dev_aic3x, | ||
154 | .codec_data = &evm_aic3x_setup, | ||
155 | }; | ||
156 | |||
157 | static struct resource evm_snd_resources[] = { | ||
158 | { | ||
159 | .start = DAVINCI_MCBSP_BASE, | ||
160 | .end = DAVINCI_MCBSP_BASE + SZ_8K - 1, | ||
161 | .flags = IORESOURCE_MEM, | ||
162 | }, | ||
163 | }; | ||
164 | |||
165 | static struct evm_snd_platform_data evm_snd_data = { | ||
166 | .tx_dma_ch = DM644X_DMACH_MCBSP_TX, | ||
167 | .rx_dma_ch = DM644X_DMACH_MCBSP_RX, | ||
168 | }; | ||
169 | |||
170 | static struct platform_device *evm_snd_device; | ||
171 | |||
172 | static int __init evm_init(void) | ||
173 | { | ||
174 | int ret; | ||
175 | |||
176 | evm_snd_device = platform_device_alloc("soc-audio", 0); | ||
177 | if (!evm_snd_device) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | platform_set_drvdata(evm_snd_device, &evm_snd_devdata); | ||
181 | evm_snd_devdata.dev = &evm_snd_device->dev; | ||
182 | evm_snd_device->dev.platform_data = &evm_snd_data; | ||
183 | |||
184 | ret = platform_device_add_resources(evm_snd_device, evm_snd_resources, | ||
185 | ARRAY_SIZE(evm_snd_resources)); | ||
186 | if (ret) { | ||
187 | platform_device_put(evm_snd_device); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | ret = platform_device_add(evm_snd_device); | ||
192 | if (ret) | ||
193 | platform_device_put(evm_snd_device); | ||
194 | |||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | static void __exit evm_exit(void) | ||
199 | { | ||
200 | platform_device_unregister(evm_snd_device); | ||
201 | } | ||
202 | |||
203 | module_init(evm_init); | ||
204 | module_exit(evm_exit); | ||
205 | |||
206 | MODULE_AUTHOR("Vladimir Barinov"); | ||
207 | MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver"); | ||
208 | MODULE_LICENSE("GPL"); | ||