Commit | Line | Data |
---|---|---|
75b41027 LG |
1 | /* |
2 | * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip. | |
3 | * | |
4 | * Author: Nicolas Pitre | |
5 | * Created: Dec 02, 2004 | |
6 | * Copyright: MontaVista Software Inc. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | */ | |
12 | ||
13 | #include <linux/init.h> | |
14 | #include <linux/module.h> | |
15 | #include <linux/platform_device.h> | |
75b41027 | 16 | |
75b41027 | 17 | #include <sound/core.h> |
75b41027 | 18 | #include <sound/ac97_codec.h> |
75b41027 | 19 | #include <sound/soc.h> |
9c636342 | 20 | #include <sound/pxa2xx-lib.h> |
75b41027 | 21 | |
a09e64fb RK |
22 | #include <mach/hardware.h> |
23 | #include <mach/pxa-regs.h> | |
75b41027 LG |
24 | |
25 | #include "pxa2xx-pcm.h" | |
596ce32b | 26 | #include "pxa2xx-ac97.h" |
75b41027 | 27 | |
75b41027 LG |
28 | static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) |
29 | { | |
9c636342 | 30 | pxa2xx_ac97_try_warm_reset(ac97); |
75b41027 | 31 | |
9c636342 | 32 | pxa2xx_ac97_finish_reset(ac97); |
75b41027 LG |
33 | } |
34 | ||
35 | static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) | |
36 | { | |
9c636342 | 37 | pxa2xx_ac97_try_cold_reset(ac97); |
7a22323b | 38 | |
9c636342 | 39 | pxa2xx_ac97_finish_reset(ac97); |
75b41027 LG |
40 | } |
41 | ||
42 | struct snd_ac97_bus_ops soc_ac97_ops = { | |
43 | .read = pxa2xx_ac97_read, | |
44 | .write = pxa2xx_ac97_write, | |
45 | .warm_reset = pxa2xx_ac97_warm_reset, | |
46 | .reset = pxa2xx_ac97_cold_reset, | |
47 | }; | |
48 | ||
49 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { | |
50 | .name = "AC97 PCM Stereo out", | |
51 | .dev_addr = __PREG(PCDR), | |
87f3dd77 | 52 | .drcmr = &DRCMR(12), |
75b41027 LG |
53 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | |
54 | DCMD_BURST32 | DCMD_WIDTH4, | |
55 | }; | |
56 | ||
57 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = { | |
58 | .name = "AC97 PCM Stereo in", | |
59 | .dev_addr = __PREG(PCDR), | |
87f3dd77 | 60 | .drcmr = &DRCMR(11), |
75b41027 LG |
61 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | |
62 | DCMD_BURST32 | DCMD_WIDTH4, | |
63 | }; | |
64 | ||
65 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = { | |
66 | .name = "AC97 Aux PCM (Slot 5) Mono out", | |
67 | .dev_addr = __PREG(MODR), | |
87f3dd77 | 68 | .drcmr = &DRCMR(10), |
75b41027 LG |
69 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | |
70 | DCMD_BURST16 | DCMD_WIDTH2, | |
71 | }; | |
72 | ||
73 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = { | |
74 | .name = "AC97 Aux PCM (Slot 5) Mono in", | |
75 | .dev_addr = __PREG(MODR), | |
87f3dd77 | 76 | .drcmr = &DRCMR(9), |
75b41027 LG |
77 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | |
78 | DCMD_BURST16 | DCMD_WIDTH2, | |
79 | }; | |
80 | ||
81 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = { | |
82 | .name = "AC97 Mic PCM (Slot 6) Mono in", | |
83 | .dev_addr = __PREG(MCDR), | |
87f3dd77 | 84 | .drcmr = &DRCMR(8), |
75b41027 LG |
85 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | |
86 | DCMD_BURST16 | DCMD_WIDTH2, | |
87 | }; | |
88 | ||
89 | #ifdef CONFIG_PM | |
dc7d7b83 | 90 | static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai) |
75b41027 | 91 | { |
9c636342 | 92 | return pxa2xx_ac97_hw_suspend(); |
75b41027 LG |
93 | } |
94 | ||
dc7d7b83 | 95 | static int pxa2xx_ac97_resume(struct snd_soc_dai *dai) |
75b41027 | 96 | { |
9c636342 | 97 | return pxa2xx_ac97_hw_resume(); |
75b41027 LG |
98 | } |
99 | ||
100 | #else | |
101 | #define pxa2xx_ac97_suspend NULL | |
102 | #define pxa2xx_ac97_resume NULL | |
103 | #endif | |
104 | ||
bdb92876 | 105 | static int pxa2xx_ac97_probe(struct platform_device *pdev, |
917f93ac | 106 | struct snd_soc_dai *dai) |
75b41027 | 107 | { |
9c636342 | 108 | return pxa2xx_ac97_hw_probe(pdev); |
75b41027 LG |
109 | } |
110 | ||
a84534dc DB |
111 | static void pxa2xx_ac97_remove(struct platform_device *pdev, |
112 | struct snd_soc_dai *dai) | |
75b41027 | 113 | { |
9c636342 | 114 | pxa2xx_ac97_hw_remove(pdev); |
75b41027 LG |
115 | } |
116 | ||
117 | static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, | |
dee89c4d MB |
118 | struct snd_pcm_hw_params *params, |
119 | struct snd_soc_dai *dai) | |
75b41027 LG |
120 | { |
121 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
917f93ac | 122 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
75b41027 LG |
123 | |
124 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
596ce32b | 125 | cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out; |
75b41027 | 126 | else |
596ce32b | 127 | cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in; |
75b41027 LG |
128 | |
129 | return 0; | |
130 | } | |
131 | ||
132 | static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, | |
dee89c4d MB |
133 | struct snd_pcm_hw_params *params, |
134 | struct snd_soc_dai *dai) | |
75b41027 LG |
135 | { |
136 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
917f93ac | 137 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
75b41027 LG |
138 | |
139 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
596ce32b | 140 | cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out; |
75b41027 | 141 | else |
596ce32b | 142 | cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in; |
75b41027 LG |
143 | |
144 | return 0; | |
145 | } | |
146 | ||
147 | static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, | |
dee89c4d MB |
148 | struct snd_pcm_hw_params *params, |
149 | struct snd_soc_dai *dai) | |
75b41027 LG |
150 | { |
151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
917f93ac | 152 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
75b41027 LG |
153 | |
154 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | |
155 | return -ENODEV; | |
156 | else | |
596ce32b | 157 | cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in; |
75b41027 LG |
158 | |
159 | return 0; | |
160 | } | |
161 | ||
596ce32b LG |
162 | #define PXA2XX_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
163 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ | |
164 | SNDRV_PCM_RATE_48000) | |
165 | ||
75b41027 LG |
166 | /* |
167 | * There is only 1 physical AC97 interface for pxa2xx, but it | |
168 | * has extra fifo's that can be used for aux DACs and ADCs. | |
169 | */ | |
917f93ac | 170 | struct snd_soc_dai pxa_ac97_dai[] = { |
75b41027 LG |
171 | { |
172 | .name = "pxa2xx-ac97", | |
173 | .id = 0, | |
3ba9e10a | 174 | .ac97_control = 1, |
75b41027 LG |
175 | .probe = pxa2xx_ac97_probe, |
176 | .remove = pxa2xx_ac97_remove, | |
177 | .suspend = pxa2xx_ac97_suspend, | |
178 | .resume = pxa2xx_ac97_resume, | |
179 | .playback = { | |
180 | .stream_name = "AC97 Playback", | |
181 | .channels_min = 2, | |
596ce32b LG |
182 | .channels_max = 2, |
183 | .rates = PXA2XX_AC97_RATES, | |
184 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | |
75b41027 LG |
185 | .capture = { |
186 | .stream_name = "AC97 Capture", | |
187 | .channels_min = 2, | |
596ce32b LG |
188 | .channels_max = 2, |
189 | .rates = PXA2XX_AC97_RATES, | |
190 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | |
75b41027 LG |
191 | .ops = { |
192 | .hw_params = pxa2xx_ac97_hw_params,}, | |
75b41027 LG |
193 | }, |
194 | { | |
195 | .name = "pxa2xx-ac97-aux", | |
196 | .id = 1, | |
3ba9e10a | 197 | .ac97_control = 1, |
75b41027 LG |
198 | .playback = { |
199 | .stream_name = "AC97 Aux Playback", | |
200 | .channels_min = 1, | |
596ce32b LG |
201 | .channels_max = 1, |
202 | .rates = PXA2XX_AC97_RATES, | |
203 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | |
75b41027 LG |
204 | .capture = { |
205 | .stream_name = "AC97 Aux Capture", | |
206 | .channels_min = 1, | |
596ce32b LG |
207 | .channels_max = 1, |
208 | .rates = PXA2XX_AC97_RATES, | |
209 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | |
75b41027 LG |
210 | .ops = { |
211 | .hw_params = pxa2xx_ac97_hw_aux_params,}, | |
75b41027 LG |
212 | }, |
213 | { | |
214 | .name = "pxa2xx-ac97-mic", | |
215 | .id = 2, | |
3ba9e10a | 216 | .ac97_control = 1, |
75b41027 LG |
217 | .capture = { |
218 | .stream_name = "AC97 Mic Capture", | |
219 | .channels_min = 1, | |
596ce32b LG |
220 | .channels_max = 1, |
221 | .rates = PXA2XX_AC97_RATES, | |
222 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | |
75b41027 LG |
223 | .ops = { |
224 | .hw_params = pxa2xx_ac97_hw_mic_params,}, | |
596ce32b | 225 | }, |
75b41027 LG |
226 | }; |
227 | ||
228 | EXPORT_SYMBOL_GPL(pxa_ac97_dai); | |
229 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
230 | ||
3f4b783c MB |
231 | static int __devinit pxa_ac97_init(void) |
232 | { | |
233 | return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | |
234 | } | |
235 | module_init(pxa_ac97_init); | |
236 | ||
237 | static void __exit pxa_ac97_exit(void) | |
238 | { | |
239 | snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | |
240 | } | |
241 | module_exit(pxa_ac97_exit); | |
242 | ||
75b41027 LG |
243 | MODULE_AUTHOR("Nicolas Pitre"); |
244 | MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); | |
245 | MODULE_LICENSE("GPL"); |