2 * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
4 * Author: Nicolas Pitre
5 * Created: Dec 02, 2004
6 * Copyright: MontaVista Software Inc.
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.
13 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
18 #include <sound/core.h>
19 #include <sound/ac97_codec.h>
20 #include <sound/soc.h>
21 #include <sound/pxa2xx-lib.h>
23 #include <mach/hardware.h>
24 #include <mach/regs-ac97.h>
26 #include <mach/audio.h>
28 #include "pxa2xx-ac97.h"
30 static void pxa2xx_ac97_warm_reset(struct snd_ac97
*ac97
)
32 pxa2xx_ac97_try_warm_reset(ac97
);
34 pxa2xx_ac97_finish_reset(ac97
);
37 static void pxa2xx_ac97_cold_reset(struct snd_ac97
*ac97
)
39 pxa2xx_ac97_try_cold_reset(ac97
);
41 pxa2xx_ac97_finish_reset(ac97
);
44 struct snd_ac97_bus_ops soc_ac97_ops
= {
45 .read
= pxa2xx_ac97_read
,
46 .write
= pxa2xx_ac97_write
,
47 .warm_reset
= pxa2xx_ac97_warm_reset
,
48 .reset
= pxa2xx_ac97_cold_reset
,
51 static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out
= {
52 .name
= "AC97 PCM Stereo out",
53 .dev_addr
= __PREG(PCDR
),
55 .dcmd
= DCMD_INCSRCADDR
| DCMD_FLOWTRG
|
56 DCMD_BURST32
| DCMD_WIDTH4
,
59 static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in
= {
60 .name
= "AC97 PCM Stereo in",
61 .dev_addr
= __PREG(PCDR
),
63 .dcmd
= DCMD_INCTRGADDR
| DCMD_FLOWSRC
|
64 DCMD_BURST32
| DCMD_WIDTH4
,
67 static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out
= {
68 .name
= "AC97 Aux PCM (Slot 5) Mono out",
69 .dev_addr
= __PREG(MODR
),
71 .dcmd
= DCMD_INCSRCADDR
| DCMD_FLOWTRG
|
72 DCMD_BURST16
| DCMD_WIDTH2
,
75 static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in
= {
76 .name
= "AC97 Aux PCM (Slot 5) Mono in",
77 .dev_addr
= __PREG(MODR
),
79 .dcmd
= DCMD_INCTRGADDR
| DCMD_FLOWSRC
|
80 DCMD_BURST16
| DCMD_WIDTH2
,
83 static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in
= {
84 .name
= "AC97 Mic PCM (Slot 6) Mono in",
85 .dev_addr
= __PREG(MCDR
),
87 .dcmd
= DCMD_INCTRGADDR
| DCMD_FLOWSRC
|
88 DCMD_BURST16
| DCMD_WIDTH2
,
92 static int pxa2xx_ac97_suspend(struct snd_soc_dai
*dai
)
94 return pxa2xx_ac97_hw_suspend();
97 static int pxa2xx_ac97_resume(struct snd_soc_dai
*dai
)
99 return pxa2xx_ac97_hw_resume();
103 #define pxa2xx_ac97_suspend NULL
104 #define pxa2xx_ac97_resume NULL
107 static int __devinit
pxa2xx_ac97_probe(struct snd_soc_dai
*dai
)
109 return pxa2xx_ac97_hw_probe(to_platform_device(dai
->dev
));
112 static int pxa2xx_ac97_remove(struct snd_soc_dai
*dai
)
114 pxa2xx_ac97_hw_remove(to_platform_device(dai
->dev
));
118 static int pxa2xx_ac97_hw_params(struct snd_pcm_substream
*substream
,
119 struct snd_pcm_hw_params
*params
,
120 struct snd_soc_dai
*cpu_dai
)
122 struct pxa2xx_pcm_dma_params
*dma_data
;
124 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
125 dma_data
= &pxa2xx_ac97_pcm_stereo_out
;
127 dma_data
= &pxa2xx_ac97_pcm_stereo_in
;
129 snd_soc_dai_set_dma_data(cpu_dai
, substream
, dma_data
);
134 static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream
*substream
,
135 struct snd_pcm_hw_params
*params
,
136 struct snd_soc_dai
*cpu_dai
)
138 struct pxa2xx_pcm_dma_params
*dma_data
;
140 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
141 dma_data
= &pxa2xx_ac97_pcm_aux_mono_out
;
143 dma_data
= &pxa2xx_ac97_pcm_aux_mono_in
;
145 snd_soc_dai_set_dma_data(cpu_dai
, substream
, dma_data
);
150 static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream
*substream
,
151 struct snd_pcm_hw_params
*params
,
152 struct snd_soc_dai
*cpu_dai
)
154 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
157 snd_soc_dai_set_dma_data(cpu_dai
, substream
,
158 &pxa2xx_ac97_pcm_mic_mono_in
);
163 #define PXA2XX_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
164 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
165 SNDRV_PCM_RATE_48000)
167 static const struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops
= {
168 .hw_params
= pxa2xx_ac97_hw_params
,
171 static const struct snd_soc_dai_ops pxa_ac97_aux_dai_ops
= {
172 .hw_params
= pxa2xx_ac97_hw_aux_params
,
175 static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops
= {
176 .hw_params
= pxa2xx_ac97_hw_mic_params
,
180 * There is only 1 physical AC97 interface for pxa2xx, but it
181 * has extra fifo's that can be used for aux DACs and ADCs.
183 static struct snd_soc_dai_driver pxa_ac97_dai_driver
[] = {
185 .name
= "pxa2xx-ac97",
187 .probe
= pxa2xx_ac97_probe
,
188 .remove
= pxa2xx_ac97_remove
,
189 .suspend
= pxa2xx_ac97_suspend
,
190 .resume
= pxa2xx_ac97_resume
,
192 .stream_name
= "AC97 Playback",
195 .rates
= PXA2XX_AC97_RATES
,
196 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,},
198 .stream_name
= "AC97 Capture",
201 .rates
= PXA2XX_AC97_RATES
,
202 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,},
203 .ops
= &pxa_ac97_hifi_dai_ops
,
206 .name
= "pxa2xx-ac97-aux",
209 .stream_name
= "AC97 Aux Playback",
212 .rates
= PXA2XX_AC97_RATES
,
213 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,},
215 .stream_name
= "AC97 Aux Capture",
218 .rates
= PXA2XX_AC97_RATES
,
219 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,},
220 .ops
= &pxa_ac97_aux_dai_ops
,
223 .name
= "pxa2xx-ac97-mic",
226 .stream_name
= "AC97 Mic Capture",
229 .rates
= PXA2XX_AC97_RATES
,
230 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,},
231 .ops
= &pxa_ac97_mic_dai_ops
,
235 EXPORT_SYMBOL_GPL(soc_ac97_ops
);
237 static __devinit
int pxa2xx_ac97_dev_probe(struct platform_device
*pdev
)
239 if (pdev
->id
!= -1) {
240 dev_err(&pdev
->dev
, "PXA2xx has only one AC97 port.\n");
244 /* Punt most of the init to the SoC probe; we may need the machine
245 * driver to do interesting things with the clocking to get us up
248 return snd_soc_register_dais(&pdev
->dev
, pxa_ac97_dai_driver
,
249 ARRAY_SIZE(pxa_ac97_dai_driver
));
252 static int __devexit
pxa2xx_ac97_dev_remove(struct platform_device
*pdev
)
254 snd_soc_unregister_dais(&pdev
->dev
, ARRAY_SIZE(pxa_ac97_dai_driver
));
258 static struct platform_driver pxa2xx_ac97_driver
= {
259 .probe
= pxa2xx_ac97_dev_probe
,
260 .remove
= __devexit_p(pxa2xx_ac97_dev_remove
),
262 .name
= "pxa2xx-ac97",
263 .owner
= THIS_MODULE
,
267 module_platform_driver(pxa2xx_ac97_driver
);
269 MODULE_AUTHOR("Nicolas Pitre");
270 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
271 MODULE_LICENSE("GPL");