diff options
-rw-r--r-- | sound/soc/at91/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/at91/at91-i2s.c (renamed from sound/soc/at91/at91rm9200-i2s.c) | 406 | ||||
-rw-r--r-- | sound/soc/at91/at91-pcm.c (renamed from sound/soc/at91/at91rm9200-pcm.c) | 203 | ||||
-rw-r--r-- | sound/soc/at91/at91-pcm.h (renamed from sound/soc/at91/at91rm9200-pcm.h) | 54 | ||||
-rw-r--r-- | sound/soc/at91/eti_b1_wm8731.c | 64 |
5 files changed, 361 insertions, 370 deletions
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile index eb12ea2d1944..b77b01ab2028 100644 --- a/sound/soc/at91/Makefile +++ b/sound/soc/at91/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | # AT91 Platform Support | 1 | # AT91 Platform Support |
2 | snd-soc-at91-objs := at91rm9200-pcm.o | 2 | snd-soc-at91-objs := at91-pcm.o |
3 | snd-soc-at91-i2s-objs := at91rm9200-i2s.o | 3 | snd-soc-at91-i2s-objs := at91-i2s.o |
4 | 4 | ||
5 | obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o | 5 | obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o |
6 | obj-$(CONFIG_SND_AT91_SOC_I2S) += snd-soc-at91-i2s.o | 6 | obj-$(CONFIG_SND_AT91_SOC_I2S) += snd-soc-at91-i2s.o |
diff --git a/sound/soc/at91/at91rm9200-i2s.c b/sound/soc/at91/at91-i2s.c index e3e6345fc8be..b452e8e6a724 100644 --- a/sound/soc/at91/at91rm9200-i2s.c +++ b/sound/soc/at91/at91-i2s.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * at91rm9200-i2s.c -- ALSA Soc Audio Layer Platform driver and DMA engine | 2 | * at91-i2s.c -- ALSA SoC I2S Audio Layer Platform driver |
3 | * | 3 | * |
4 | * Author: Frank Mandarino <fmandarino@endrelia.com> | 4 | * Author: Frank Mandarino <fmandarino@endrelia.com> |
5 | * Endrelia Technologies Inc. | 5 | * Endrelia Technologies Inc. |
@@ -28,34 +28,41 @@ | |||
28 | #include <sound/initval.h> | 28 | #include <sound/initval.h> |
29 | #include <sound/soc.h> | 29 | #include <sound/soc.h> |
30 | 30 | ||
31 | #include <asm/arch/at91rm9200.h> | ||
32 | #include <asm/arch/at91rm9200_ssc.h> | ||
33 | #include <asm/arch/at91rm9200_pdc.h> | ||
34 | #include <asm/arch/hardware.h> | 31 | #include <asm/arch/hardware.h> |
32 | #include <asm/arch/at91_pmc.h> | ||
33 | #include <asm/arch/at91_ssc.h> | ||
34 | #include <asm/arch/at91_pdc.h> | ||
35 | 35 | ||
36 | #include "at91rm9200-pcm.h" | 36 | #include "at91-pcm.h" |
37 | 37 | ||
38 | #if 0 | 38 | #if 0 |
39 | #define DBG(x...) printk(KERN_DEBUG "at91rm9200-i2s:" x) | 39 | #define DBG(x...) printk(KERN_DEBUG "at91-i2s:" x) |
40 | #else | 40 | #else |
41 | #define DBG(x...) | 41 | #define DBG(x...) |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #define AT91RM9200_I2S_DAIFMT \ | 44 | #if defined(CONFIG_ARCH_AT91SAM9260) |
45 | #define NUM_SSC_DEVICES 1 | ||
46 | #else | ||
47 | #define NUM_SSC_DEVICES 3 | ||
48 | #endif | ||
49 | |||
50 | |||
51 | #define AT91_I2S_DAIFMT \ | ||
45 | (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_NB_NF) | 52 | (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_NB_NF) |
46 | 53 | ||
47 | #define AT91RM9200_I2S_DIR \ | 54 | #define AT91_I2S_DIR \ |
48 | (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) | 55 | (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) |
49 | 56 | ||
50 | /* priv is (SSC_CMR.DIV << 16 | SSC_TCMR.PERIOD ) */ | 57 | /* priv is (SSC_CMR.DIV << 16 | SSC_TCMR.PERIOD ) */ |
51 | static struct snd_soc_dai_mode at91rm9200_i2s[] = { | 58 | static struct snd_soc_dai_mode at91_i2s[] = { |
52 | 59 | ||
53 | /* 8k: BCLK = (MCLK/10) = (60MHz/50) = 1.2MHz */ | 60 | /* 8k: BCLK = (MCLK/10) = (60MHz/50) = 1.2MHz */ |
54 | { | 61 | { |
55 | .fmt = AT91RM9200_I2S_DAIFMT, | 62 | .fmt = AT91_I2S_DAIFMT, |
56 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, | 63 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, |
57 | .pcmrate = SNDRV_PCM_RATE_8000, | 64 | .pcmrate = SNDRV_PCM_RATE_8000, |
58 | .pcmdir = AT91RM9200_I2S_DIR, | 65 | .pcmdir = AT91_I2S_DIR, |
59 | .flags = SND_SOC_DAI_BFS_DIV, | 66 | .flags = SND_SOC_DAI_BFS_DIV, |
60 | .fs = 1500, | 67 | .fs = 1500, |
61 | .bfs = SND_SOC_FSBD(10), | 68 | .bfs = SND_SOC_FSBD(10), |
@@ -64,10 +71,10 @@ static struct snd_soc_dai_mode at91rm9200_i2s[] = { | |||
64 | 71 | ||
65 | /* 16k: BCLK = (MCLK/3) ~= (60MHz/14) = 4.285714MHz */ | 72 | /* 16k: BCLK = (MCLK/3) ~= (60MHz/14) = 4.285714MHz */ |
66 | { | 73 | { |
67 | .fmt = AT91RM9200_I2S_DAIFMT, | 74 | .fmt = AT91_I2S_DAIFMT, |
68 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, | 75 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, |
69 | .pcmrate = SNDRV_PCM_RATE_16000, | 76 | .pcmrate = SNDRV_PCM_RATE_16000, |
70 | .pcmdir = AT91RM9200_I2S_DIR, | 77 | .pcmdir = AT91_I2S_DIR, |
71 | .flags = SND_SOC_DAI_BFS_DIV, | 78 | .flags = SND_SOC_DAI_BFS_DIV, |
72 | .fs = 750, | 79 | .fs = 750, |
73 | .bfs = SND_SOC_FSBD(3), | 80 | .bfs = SND_SOC_FSBD(3), |
@@ -76,10 +83,10 @@ static struct snd_soc_dai_mode at91rm9200_i2s[] = { | |||
76 | 83 | ||
77 | /* 32k: BCLK = (MCLK/3) ~= (60MHz/14) = 4.285714MHz */ | 84 | /* 32k: BCLK = (MCLK/3) ~= (60MHz/14) = 4.285714MHz */ |
78 | { | 85 | { |
79 | .fmt = AT91RM9200_I2S_DAIFMT, | 86 | .fmt = AT91_I2S_DAIFMT, |
80 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, | 87 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, |
81 | .pcmrate = SNDRV_PCM_RATE_32000, | 88 | .pcmrate = SNDRV_PCM_RATE_32000, |
82 | .pcmdir = AT91RM9200_I2S_DIR, | 89 | .pcmdir = AT91_I2S_DIR, |
83 | .flags = SND_SOC_DAI_BFS_DIV, | 90 | .flags = SND_SOC_DAI_BFS_DIV, |
84 | .fs = 375, | 91 | .fs = 375, |
85 | .bfs = SND_SOC_FSBD(3), | 92 | .bfs = SND_SOC_FSBD(3), |
@@ -88,10 +95,10 @@ static struct snd_soc_dai_mode at91rm9200_i2s[] = { | |||
88 | 95 | ||
89 | /* 48k: BCLK = (MCLK/5) ~= (60MHz/26) = 2.3076923MHz */ | 96 | /* 48k: BCLK = (MCLK/5) ~= (60MHz/26) = 2.3076923MHz */ |
90 | { | 97 | { |
91 | .fmt = AT91RM9200_I2S_DAIFMT, | 98 | .fmt = AT91_I2S_DAIFMT, |
92 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, | 99 | .pcmfmt = SNDRV_PCM_FMTBIT_S16_LE, |
93 | .pcmrate = SNDRV_PCM_RATE_48000, | 100 | .pcmrate = SNDRV_PCM_RATE_48000, |
94 | .pcmdir = AT91RM9200_I2S_DIR, | 101 | .pcmdir = AT91_I2S_DIR, |
95 | .flags = SND_SOC_DAI_BFS_DIV, | 102 | .flags = SND_SOC_DAI_BFS_DIV, |
96 | .fs = 250, | 103 | .fs = 250, |
97 | .bfs SND_SOC_FSBD(5), | 104 | .bfs SND_SOC_FSBD(5), |
@@ -101,78 +108,26 @@ static struct snd_soc_dai_mode at91rm9200_i2s[] = { | |||
101 | 108 | ||
102 | 109 | ||
103 | /* | 110 | /* |
104 | * SSC registers required by the PCM DMA engine. | 111 | * SSC PDC registers required by the PCM DMA engine. |
105 | */ | 112 | */ |
106 | static struct at91rm9200_ssc_regs ssc_reg[3] = { | 113 | static struct at91_pdc_regs pdc_tx_reg = { |
107 | { | 114 | .xpr = AT91_PDC_TPR, |
108 | .cr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_SSC_CR), | 115 | .xcr = AT91_PDC_TCR, |
109 | .ier = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_SSC_IER), | 116 | .xnpr = AT91_PDC_TNPR, |
110 | .idr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_SSC_IDR), | 117 | .xncr = AT91_PDC_TNCR, |
111 | }, | ||
112 | { | ||
113 | .cr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_SSC_CR), | ||
114 | .ier = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_SSC_IER), | ||
115 | .idr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_SSC_IDR), | ||
116 | }, | ||
117 | { | ||
118 | .cr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_SSC_CR), | ||
119 | .ier = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_SSC_IER), | ||
120 | .idr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_SSC_IDR), | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static struct at91rm9200_pdc_regs pdc_tx_reg[3] = { | ||
125 | { | ||
126 | .xpr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_TPR), | ||
127 | .xcr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_TCR), | ||
128 | .xnpr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_TNPR), | ||
129 | .xncr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_TNCR), | ||
130 | .ptcr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_PTCR), | ||
131 | }, | ||
132 | { | ||
133 | .xpr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_TPR), | ||
134 | .xcr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_TCR), | ||
135 | .xnpr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_TNPR), | ||
136 | .xncr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_TNCR), | ||
137 | .ptcr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_PTCR), | ||
138 | }, | ||
139 | { | ||
140 | .xpr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_TPR), | ||
141 | .xcr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_TCR), | ||
142 | .xnpr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_TNPR), | ||
143 | .xncr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_TNCR), | ||
144 | .ptcr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_PTCR), | ||
145 | }, | ||
146 | }; | 118 | }; |
147 | 119 | ||
148 | static struct at91rm9200_pdc_regs pdc_rx_reg[3] = { | 120 | static struct at91_pdc_regs pdc_rx_reg = { |
149 | { | 121 | .xpr = AT91_PDC_RPR, |
150 | .xpr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_RPR), | 122 | .xcr = AT91_PDC_RCR, |
151 | .xcr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_RCR), | 123 | .xnpr = AT91_PDC_RNPR, |
152 | .xnpr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_RNPR), | 124 | .xncr = AT91_PDC_RNCR, |
153 | .xncr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_RNCR), | ||
154 | .ptcr = (void __iomem *) (AT91_VA_BASE_SSC0 + AT91_PDC_PTCR), | ||
155 | }, | ||
156 | { | ||
157 | .xpr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_RPR), | ||
158 | .xcr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_RCR), | ||
159 | .xnpr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_RNPR), | ||
160 | .xncr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_RNCR), | ||
161 | .ptcr = (void __iomem *) (AT91_VA_BASE_SSC1 + AT91_PDC_PTCR), | ||
162 | }, | ||
163 | { | ||
164 | .xpr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_RPR), | ||
165 | .xcr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_RCR), | ||
166 | .xnpr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_RNPR), | ||
167 | .xncr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_RNCR), | ||
168 | .ptcr = (void __iomem *) (AT91_VA_BASE_SSC2 + AT91_PDC_PTCR), | ||
169 | }, | ||
170 | }; | 125 | }; |
171 | 126 | ||
172 | /* | 127 | /* |
173 | * SSC & PDC status bits for transmit and receive. | 128 | * SSC & PDC status bits for transmit and receive. |
174 | */ | 129 | */ |
175 | static struct at91rm9200_ssc_mask ssc_tx_mask = { | 130 | static struct at91_ssc_mask ssc_tx_mask = { |
176 | .ssc_enable = AT91_SSC_TXEN, | 131 | .ssc_enable = AT91_SSC_TXEN, |
177 | .ssc_disable = AT91_SSC_TXDIS, | 132 | .ssc_disable = AT91_SSC_TXDIS, |
178 | .ssc_endx = AT91_SSC_ENDTX, | 133 | .ssc_endx = AT91_SSC_ENDTX, |
@@ -181,7 +136,7 @@ static struct at91rm9200_ssc_mask ssc_tx_mask = { | |||
181 | .pdc_disable = AT91_PDC_TXTDIS, | 136 | .pdc_disable = AT91_PDC_TXTDIS, |
182 | }; | 137 | }; |
183 | 138 | ||
184 | static struct at91rm9200_ssc_mask ssc_rx_mask = { | 139 | static struct at91_ssc_mask ssc_rx_mask = { |
185 | .ssc_enable = AT91_SSC_RXEN, | 140 | .ssc_enable = AT91_SSC_RXEN, |
186 | .ssc_disable = AT91_SSC_RXDIS, | 141 | .ssc_disable = AT91_SSC_RXDIS, |
187 | .ssc_endx = AT91_SSC_ENDRX, | 142 | .ssc_endx = AT91_SSC_ENDRX, |
@@ -190,61 +145,61 @@ static struct at91rm9200_ssc_mask ssc_rx_mask = { | |||
190 | .pdc_disable = AT91_PDC_RXTDIS, | 145 | .pdc_disable = AT91_PDC_RXTDIS, |
191 | }; | 146 | }; |
192 | 147 | ||
193 | /* | ||
194 | * A MUTEX is used to protect an SSC initialzed flag which allows | ||
195 | * the substream hw_params() call to initialize the SSC only if | ||
196 | * there are no other substreams open. If there are other | ||
197 | * substreams open, the hw_param() call can only check that | ||
198 | * it is using the same format and rate. | ||
199 | */ | ||
200 | static DECLARE_MUTEX(ssc0_mutex); | ||
201 | static DECLARE_MUTEX(ssc1_mutex); | ||
202 | static DECLARE_MUTEX(ssc2_mutex); | ||
203 | 148 | ||
204 | /* | 149 | /* |
205 | * DMA parameters. | 150 | * DMA parameters. |
206 | */ | 151 | */ |
207 | static at91rm9200_pcm_dma_params_t ssc_dma_params[3][2] = { | 152 | static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = { |
208 | {{ | 153 | {{ |
209 | .name = "SSC0/I2S PCM Stereo out", | 154 | .name = "SSC0/I2S PCM Stereo out", |
210 | .ssc = &ssc_reg[0], | 155 | .pdc = &pdc_tx_reg, |
211 | .pdc = &pdc_tx_reg[0], | ||
212 | .mask = &ssc_tx_mask, | 156 | .mask = &ssc_tx_mask, |
213 | }, | 157 | }, |
214 | { | 158 | { |
215 | .name = "SSC0/I2S PCM Stereo in", | 159 | .name = "SSC0/I2S PCM Stereo in", |
216 | .ssc = &ssc_reg[0], | 160 | .pdc = &pdc_rx_reg, |
217 | .pdc = &pdc_rx_reg[0], | ||
218 | .mask = &ssc_rx_mask, | 161 | .mask = &ssc_rx_mask, |
219 | }}, | 162 | }}, |
163 | #if NUM_SSC_DEVICES == 3 | ||
220 | {{ | 164 | {{ |
221 | .name = "SSC1/I2S PCM Stereo out", | 165 | .name = "SSC1/I2S PCM Stereo out", |
222 | .ssc = &ssc_reg[1], | 166 | .pdc = &pdc_tx_reg, |
223 | .pdc = &pdc_tx_reg[1], | ||
224 | .mask = &ssc_tx_mask, | 167 | .mask = &ssc_tx_mask, |
225 | }, | 168 | }, |
226 | { | 169 | { |
227 | .name = "SSC1/I2S PCM Stereo in", | 170 | .name = "SSC1/I2S PCM Stereo in", |
228 | .ssc = &ssc_reg[1], | 171 | .pdc = &pdc_rx_reg, |
229 | .pdc = &pdc_rx_reg[1], | ||
230 | .mask = &ssc_rx_mask, | 172 | .mask = &ssc_rx_mask, |
231 | }}, | 173 | }}, |
232 | {{ | 174 | {{ |
233 | .name = "SSC2/I2S PCM Stereo out", | 175 | .name = "SSC2/I2S PCM Stereo out", |
234 | .ssc = &ssc_reg[2], | 176 | .pdc = &pdc_tx_reg, |
235 | .pdc = &pdc_tx_reg[2], | ||
236 | .mask = &ssc_tx_mask, | 177 | .mask = &ssc_tx_mask, |
237 | }, | 178 | }, |
238 | { | 179 | { |
239 | .name = "SSC1/I2S PCM Stereo in", | 180 | .name = "SSC1/I2S PCM Stereo in", |
240 | .ssc = &ssc_reg[2], | 181 | .pdc = &pdc_rx_reg, |
241 | .pdc = &pdc_rx_reg[2], | ||
242 | .mask = &ssc_rx_mask, | 182 | .mask = &ssc_rx_mask, |
243 | }}, | 183 | }}, |
184 | #endif | ||
244 | }; | 185 | }; |
245 | 186 | ||
246 | 187 | ||
247 | struct at91rm9200_ssc_state { | 188 | /* |
189 | * A MUTEX is used to protect an SSC initialzed flag which allows | ||
190 | * the substream hw_params() call to initialize the SSC only if | ||
191 | * there are no other substreams open. If there are other | ||
192 | * substreams open, the hw_param() call can only check that | ||
193 | * it is using the same format and rate. | ||
194 | */ | ||
195 | static DECLARE_MUTEX(ssc0_mutex); | ||
196 | #if NUM_SSC_DEVICES == 3 | ||
197 | static DECLARE_MUTEX(ssc1_mutex); | ||
198 | static DECLARE_MUTEX(ssc2_mutex); | ||
199 | #endif | ||
200 | |||
201 | |||
202 | struct at91_ssc_state { | ||
248 | u32 ssc_cmr; | 203 | u32 ssc_cmr; |
249 | u32 ssc_rcmr; | 204 | u32 ssc_rcmr; |
250 | u32 ssc_rfmr; | 205 | u32 ssc_rfmr; |
@@ -254,33 +209,30 @@ struct at91rm9200_ssc_state { | |||
254 | u32 ssc_imr; | 209 | u32 ssc_imr; |
255 | }; | 210 | }; |
256 | 211 | ||
257 | static struct at91rm9200_ssc_info { | 212 | |
213 | static struct at91_ssc_info { | ||
258 | char *name; | 214 | char *name; |
259 | void __iomem *ssc_base; | 215 | struct at91_ssc_periph ssc; |
260 | u32 pid; | ||
261 | spinlock_t lock; /* lock for dir_mask */ | 216 | spinlock_t lock; /* lock for dir_mask */ |
262 | int dir_mask; /* 0=unused, 1=playback, 2=capture */ | 217 | int dir_mask; /* 0=unused, 1=playback, 2=capture */ |
263 | struct semaphore *mutex; | 218 | struct semaphore *mutex; |
264 | int initialized; | 219 | int initialized; |
265 | int pcmfmt; | 220 | int pcmfmt; |
266 | int rate; | 221 | int rate; |
267 | at91rm9200_pcm_dma_params_t *dma_params[2]; | 222 | struct at91_pcm_dma_params *dma_params[2]; |
268 | struct at91rm9200_ssc_state ssc_state; | 223 | struct at91_ssc_state ssc_state; |
269 | 224 | ||
270 | } ssc_info[3] = { | 225 | } ssc_info[NUM_SSC_DEVICES] = { |
271 | { | 226 | { |
272 | .name = "ssc0", | 227 | .name = "ssc0", |
273 | .ssc_base = (void __iomem *) AT91_VA_BASE_SSC0, | ||
274 | .pid = AT91_ID_SSC0, | ||
275 | .lock = SPIN_LOCK_UNLOCKED, | 228 | .lock = SPIN_LOCK_UNLOCKED, |
276 | .dir_mask = 0, | 229 | .dir_mask = 0, |
277 | .mutex = &ssc0_mutex, | 230 | .mutex = &ssc0_mutex, |
278 | .initialized = 0, | 231 | .initialized = 0, |
279 | }, | 232 | }, |
233 | #if NUM_SSC_DEVICES == 3 | ||
280 | { | 234 | { |
281 | .name = "ssc1", | 235 | .name = "ssc1", |
282 | .ssc_base = (void __iomem *) AT91_VA_BASE_SSC1, | ||
283 | .pid = AT91_ID_SSC1, | ||
284 | .lock = SPIN_LOCK_UNLOCKED, | 236 | .lock = SPIN_LOCK_UNLOCKED, |
285 | .dir_mask = 0, | 237 | .dir_mask = 0, |
286 | .mutex = &ssc1_mutex, | 238 | .mutex = &ssc1_mutex, |
@@ -288,25 +240,24 @@ static struct at91rm9200_ssc_info { | |||
288 | }, | 240 | }, |
289 | { | 241 | { |
290 | .name = "ssc2", | 242 | .name = "ssc2", |
291 | .ssc_base = (void __iomem *) AT91_VA_BASE_SSC2, | ||
292 | .pid = AT91_ID_SSC2, | ||
293 | .lock = SPIN_LOCK_UNLOCKED, | 243 | .lock = SPIN_LOCK_UNLOCKED, |
294 | .dir_mask = 0, | 244 | .dir_mask = 0, |
295 | .mutex = &ssc2_mutex, | 245 | .mutex = &ssc2_mutex, |
296 | .initialized = 0, | 246 | .initialized = 0, |
297 | }, | 247 | }, |
248 | #endif | ||
298 | }; | 249 | }; |
299 | 250 | ||
300 | 251 | ||
301 | static irqreturn_t at91rm9200_i2s_interrupt(int irq, void *dev_id) | 252 | static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id) |
302 | { | 253 | { |
303 | struct at91rm9200_ssc_info *ssc_p = dev_id; | 254 | struct at91_ssc_info *ssc_p = dev_id; |
304 | at91rm9200_pcm_dma_params_t *dma_params; | 255 | struct at91_pcm_dma_params *dma_params; |
305 | u32 ssc_sr; | 256 | u32 ssc_sr; |
306 | int i; | 257 | int i; |
307 | 258 | ||
308 | ssc_sr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_SR) | 259 | ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR) |
309 | & at91_ssc_read(ssc_p->ssc_base + AT91_SSC_IMR); | 260 | & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR); |
310 | 261 | ||
311 | /* | 262 | /* |
312 | * Loop through the substreams attached to this SSC. If | 263 | * Loop through the substreams attached to this SSC. If |
@@ -327,14 +278,14 @@ static irqreturn_t at91rm9200_i2s_interrupt(int irq, void *dev_id) | |||
327 | return IRQ_HANDLED; | 278 | return IRQ_HANDLED; |
328 | } | 279 | } |
329 | 280 | ||
330 | static int at91rm9200_i2s_startup(struct snd_pcm_substream *substream) | 281 | static int at91_i2s_startup(struct snd_pcm_substream *substream) |
331 | { | 282 | { |
332 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 283 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
333 | struct at91rm9200_ssc_info *ssc_p = &ssc_info[rtd->cpu_dai->id]; | 284 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->cpu_dai->id]; |
334 | int dir_mask; | 285 | int dir_mask; |
335 | 286 | ||
336 | DBG("i2s_startup: SSC_SR=0x%08lx\n", | 287 | DBG("i2s_startup: SSC_SR=0x%08lx\n", |
337 | at91_ssc_read(ssc_p->ssc_base + AT91_SSC_SR)); | 288 | at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)); |
338 | dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2; | 289 | dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2; |
339 | 290 | ||
340 | spin_lock_irq(&ssc_p->lock); | 291 | spin_lock_irq(&ssc_p->lock); |
@@ -348,20 +299,22 @@ static int at91rm9200_i2s_startup(struct snd_pcm_substream *substream) | |||
348 | return 0; | 299 | return 0; |
349 | } | 300 | } |
350 | 301 | ||
351 | static void at91rm9200_i2s_shutdown(struct snd_pcm_substream *substream) | 302 | static void at91_i2s_shutdown(struct snd_pcm_substream *substream) |
352 | { | 303 | { |
353 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 304 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
354 | struct at91rm9200_ssc_info *ssc_p = &ssc_info[rtd->cpu_dai->id]; | 305 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->cpu_dai->id]; |
355 | at91rm9200_pcm_dma_params_t *dma_params = rtd->cpu_dai->dma_data; | 306 | struct at91_pcm_dma_params *dma_params = rtd->cpu_dai->dma_data; |
356 | int dir, dir_mask; | 307 | int dir, dir_mask; |
357 | 308 | ||
358 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | 309 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; |
359 | 310 | ||
360 | if (dma_params != NULL) { | 311 | if (dma_params != NULL) { |
361 | at91_ssc_write(dma_params->ssc->cr, dma_params->mask->ssc_disable); | 312 | at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR, |
313 | dma_params->mask->ssc_disable); | ||
362 | DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"), | 314 | DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"), |
363 | at91_ssc_read(ssc_p->ssc_base + AT91_SSC_SR)); | 315 | at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)); |
364 | 316 | ||
317 | dma_params->ssc_base = NULL; | ||
365 | dma_params->substream = NULL; | 318 | dma_params->substream = NULL; |
366 | ssc_p->dma_params[dir] = NULL; | 319 | ssc_p->dma_params[dir] = NULL; |
367 | } | 320 | } |
@@ -372,14 +325,14 @@ static void at91rm9200_i2s_shutdown(struct snd_pcm_substream *substream) | |||
372 | ssc_p->dir_mask &= ~dir_mask; | 325 | ssc_p->dir_mask &= ~dir_mask; |
373 | if (!ssc_p->dir_mask) { | 326 | if (!ssc_p->dir_mask) { |
374 | /* Shutdown the SSC clock. */ | 327 | /* Shutdown the SSC clock. */ |
375 | DBG("Stopping pid %d clock\n", ssc_p->pid); | 328 | DBG("Stopping pid %d clock\n", ssc_p->ssc.pid); |
376 | at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->pid); | 329 | at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid); |
377 | 330 | ||
378 | if (ssc_p->initialized) | 331 | if (ssc_p->initialized) |
379 | free_irq(ssc_p->pid, ssc_p); | 332 | free_irq(ssc_p->ssc.pid, ssc_p); |
380 | 333 | ||
381 | /* Reset the SSC */ | 334 | /* Reset the SSC */ |
382 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CR, AT91_SSC_SWRST); | 335 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST); |
383 | 336 | ||
384 | /* Force a re-init on the next hw_params() call. */ | 337 | /* Force a re-init on the next hw_params() call. */ |
385 | ssc_p->initialized = 0; | 338 | ssc_p->initialized = 0; |
@@ -388,10 +341,10 @@ static void at91rm9200_i2s_shutdown(struct snd_pcm_substream *substream) | |||
388 | } | 341 | } |
389 | 342 | ||
390 | #ifdef CONFIG_PM | 343 | #ifdef CONFIG_PM |
391 | static int at91rm9200_i2s_suspend(struct platform_device *pdev, | 344 | static int at91_i2s_suspend(struct platform_device *pdev, |
392 | struct snd_soc_cpu_dai *dai) | 345 | struct snd_soc_cpu_dai *dai) |
393 | { | 346 | { |
394 | struct at91rm9200_ssc_info *ssc_p; | 347 | struct at91_ssc_info *ssc_p; |
395 | 348 | ||
396 | if(!dai->active) | 349 | if(!dai->active) |
397 | return 0; | 350 | return 0; |
@@ -399,27 +352,27 @@ static int at91rm9200_i2s_suspend(struct platform_device *pdev, | |||
399 | ssc_p = &ssc_info[dai->id]; | 352 | ssc_p = &ssc_info[dai->id]; |
400 | 353 | ||
401 | /* Save the status register before disabling transmit and receive. */ | 354 | /* Save the status register before disabling transmit and receive. */ |
402 | ssc_p->state->ssc_sr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_SR); | 355 | ssc_p->state->ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR); |
403 | at91_ssc_write(ssc_p->ssc_base + | 356 | at91_ssc_write(ssc_p->ssc.base + |
404 | AT91_SSC_CR, AT91_SSC_TXDIS | AT91_SSC_RXDIS); | 357 | AT91_SSC_CR, AT91_SSC_TXDIS | AT91_SSC_RXDIS); |
405 | 358 | ||
406 | /* Save the current interrupt mask, then disable unmasked interrupts. */ | 359 | /* Save the current interrupt mask, then disable unmasked interrupts. */ |
407 | ssc_p->state->ssc_imr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_IMR); | 360 | ssc_p->state->ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR); |
408 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_IDR, ssc_p->state->ssc_imr); | 361 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->state->ssc_imr); |
409 | 362 | ||
410 | ssc_p->state->ssc_cmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_CMR); | 363 | ssc_p->state->ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR); |
411 | ssc_p->state->ssc_rcmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_RCMR); | 364 | ssc_p->state->ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); |
412 | ssc_p->state->ssc_rfmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_RCMR); | 365 | ssc_p->state->ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); |
413 | ssc_p->state->ssc_tcmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_RCMR); | 366 | ssc_p->state->ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); |
414 | ssc_p->state->ssc_tfmr = at91_ssc_read(ssc_p->ssc_base + AT91_SSC_RCMR); | 367 | ssc_p->state->ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); |
415 | 368 | ||
416 | return 0; | 369 | return 0; |
417 | } | 370 | } |
418 | 371 | ||
419 | static int at91rm9200_i2s_resume(struct platform_device *pdev, | 372 | static int at91_i2s_resume(struct platform_device *pdev, |
420 | struct snd_soc_cpu_dai *dai) | 373 | struct snd_soc_cpu_dai *dai) |
421 | { | 374 | { |
422 | struct at91rm9200_ssc_info *ssc_p; | 375 | struct at91_ssc_info *ssc_p; |
423 | u32 cr_mask; | 376 | u32 cr_mask; |
424 | 377 | ||
425 | if(!dai->active) | 378 | if(!dai->active) |
@@ -427,15 +380,15 @@ static int at91rm9200_i2s_resume(struct platform_device *pdev, | |||
427 | 380 | ||
428 | ssc_p = &ssc_info[dai->id]; | 381 | ssc_p = &ssc_info[dai->id]; |
429 | 382 | ||
430 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, ssc_p->state->ssc_tfmr); | 383 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->state->ssc_tfmr); |
431 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, ssc_p->state->ssc_tcmr); | 384 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->state->ssc_tcmr); |
432 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, ssc_p->state->ssc_rfmr); | 385 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->state->ssc_rfmr); |
433 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, ssc_p->state->ssc_rcmr); | 386 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->state->ssc_rcmr); |
434 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CMR, ssc_p->state->ssc_cmr); | 387 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->state->ssc_cmr); |
435 | 388 | ||
436 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_IER, ssc_p->state->ssc_imr); | 389 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->state->ssc_imr); |
437 | 390 | ||
438 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CR, | 391 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, |
439 | ((ssc_p->state->ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) | | 392 | ((ssc_p->state->ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) | |
440 | ((ssc_p->state->ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0)); | 393 | ((ssc_p->state->ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0)); |
441 | 394 | ||
@@ -443,11 +396,11 @@ static int at91rm9200_i2s_resume(struct platform_device *pdev, | |||
443 | } | 396 | } |
444 | 397 | ||
445 | #else | 398 | #else |
446 | #define at91rm9200_i2s_suspend NULL | 399 | #define at91_i2s_suspend NULL |
447 | #define at91rm9200_i2s_resume NULL | 400 | #define at91_i2s_resume NULL |
448 | #endif | 401 | #endif |
449 | 402 | ||
450 | static unsigned int at91rm9200_i2s_config_sysclk( | 403 | static unsigned int at91_i2s_config_sysclk( |
451 | struct snd_soc_cpu_dai *iface, struct snd_soc_clock_info *info, | 404 | struct snd_soc_cpu_dai *iface, struct snd_soc_clock_info *info, |
452 | unsigned int clk) | 405 | unsigned int clk) |
453 | { | 406 | { |
@@ -457,17 +410,16 @@ static unsigned int at91rm9200_i2s_config_sysclk( | |||
457 | return 12000000; | 410 | return 12000000; |
458 | } | 411 | } |
459 | 412 | ||
460 | static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | 413 | static int at91_i2s_hw_params(struct snd_pcm_substream *substream, |
461 | struct snd_pcm_hw_params *params) | 414 | struct snd_pcm_hw_params *params) |
462 | { | 415 | { |
463 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 416 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
464 | int id = rtd->cpu_dai->id; | 417 | int id = rtd->cpu_dai->id; |
465 | struct at91rm9200_ssc_info *ssc_p = &ssc_info[id]; | 418 | struct at91_ssc_info *ssc_p = &ssc_info[id]; |
466 | at91rm9200_pcm_dma_params_t *dma_params; | 419 | struct at91_pcm_dma_params *dma_params; |
467 | unsigned int pcmfmt, rate; | 420 | unsigned int pcmfmt, rate; |
468 | int dir, channels, bits; | 421 | int dir, channels, bits; |
469 | struct clk *mck_clk; | 422 | struct clk *mck_clk; |
470 | unsigned long bclk; | ||
471 | u32 div, period, tfmr, rfmr, tcmr, rcmr; | 423 | u32 div, period, tfmr, rfmr, tcmr, rcmr; |
472 | int ret; | 424 | int ret; |
473 | 425 | ||
@@ -479,6 +431,7 @@ static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | |||
479 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | 431 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; |
480 | 432 | ||
481 | dma_params = &ssc_dma_params[id][dir]; | 433 | dma_params = &ssc_dma_params[id][dir]; |
434 | dma_params->ssc_base = ssc_p->ssc.base; | ||
482 | dma_params->substream = substream; | 435 | dma_params->substream = substream; |
483 | 436 | ||
484 | ssc_p->dma_params[dir] = dma_params; | 437 | ssc_p->dma_params[dir] = dma_params; |
@@ -495,7 +448,7 @@ static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | |||
495 | dma_params->pdc_xfer_size = 2; | 448 | dma_params->pdc_xfer_size = 2; |
496 | break; | 449 | break; |
497 | default: | 450 | default: |
498 | printk(KERN_WARNING "at91rm9200-i2s: unsupported format %x\n", | 451 | printk(KERN_WARNING "at91-i2s: unsupported format %x\n", |
499 | pcmfmt); | 452 | pcmfmt); |
500 | return -EINVAL; | 453 | return -EINVAL; |
501 | } | 454 | } |
@@ -509,46 +462,45 @@ static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | |||
509 | */ | 462 | */ |
510 | if (ssc_p->initialized) { | 463 | if (ssc_p->initialized) { |
511 | if (pcmfmt != ssc_p->pcmfmt || rate != ssc_p->rate) { | 464 | if (pcmfmt != ssc_p->pcmfmt || rate != ssc_p->rate) { |
512 | printk(KERN_WARNING "at91rm9200-i2s: " | 465 | printk(KERN_WARNING "at91-i2s: " |
513 | "incompatible substream in other direction\n"); | 466 | "incompatible substream in other direction\n"); |
514 | up(ssc_p->mutex); | 467 | up(ssc_p->mutex); |
515 | return -EINVAL; | 468 | return -EINVAL; |
516 | } | 469 | } |
517 | } else { | 470 | } else { |
518 | /* Enable PMC peripheral clock for this SSC */ | 471 | /* Enable PMC peripheral clock for this SSC */ |
519 | DBG("Starting pid %d clock\n", ssc_p->pid); | 472 | DBG("Starting pid %d clock\n", ssc_p->ssc.pid); |
520 | at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->pid); | 473 | at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid); |
521 | 474 | ||
522 | /* Reset the SSC */ | 475 | /* Reset the SSC */ |
523 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CR, AT91_SSC_SWRST); | 476 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST); |
524 | |||
525 | at91_ssc_write(ssc_p->ssc_base + AT91_PDC_RPR, 0); | ||
526 | at91_ssc_write(ssc_p->ssc_base + AT91_PDC_RCR, 0); | ||
527 | at91_ssc_write(ssc_p->ssc_base + AT91_PDC_RNPR, 0); | ||
528 | at91_ssc_write(ssc_p->ssc_base + AT91_PDC_RNCR, 0); | ||
529 | at91_ssc_write(ssc_p->ssc_base + AT91_PDC_TPR, 0); | ||
530 | at91_ssc_write(ssc_p->ssc_base + AT91_PDC_TCR, 0); | ||
531 | at91_ssc_write(ssc_p->ssc_base + AT91_PDC_TNPR, 0); | ||
532 | at91_ssc_write(ssc_p->ssc_base + AT91_PDC_TNCR, 0); | ||
533 | 477 | ||
534 | mck_clk = clk_get(NULL, "mck"); | 478 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RPR, 0); |
479 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RCR, 0); | ||
480 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RNPR, 0); | ||
481 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RNCR, 0); | ||
482 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TPR, 0); | ||
483 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TCR, 0); | ||
484 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNPR, 0); | ||
485 | at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNCR, 0); | ||
535 | 486 | ||
536 | div = rtd->cpu_dai->dai_runtime.priv >> 16; | 487 | div = rtd->cpu_dai->dai_runtime.priv >> 16; |
537 | period = rtd->cpu_dai->dai_runtime.priv & 0xffff; | 488 | period = rtd->cpu_dai->dai_runtime.priv & 0xffff; |
538 | bclk = 60000000 / (2 * div); | ||
539 | 489 | ||
540 | DBG("mck %ld fsbd %d bfs %d bfs_real %d bclk %ld div %d period %d\n", | 490 | mck_clk = clk_get(NULL, "mck"); |
491 | |||
492 | DBG("mck %lu fsbd %u bfs %llu bfs_real %u bclk %lu div %u period %u\n", | ||
541 | clk_get_rate(mck_clk), | 493 | clk_get_rate(mck_clk), |
542 | SND_SOC_FSBD(6), | 494 | SND_SOC_FSBD(6), |
543 | rtd->cpu_dai->dai_runtime.bfs, | 495 | rtd->cpu_dai->dai_runtime.bfs, |
544 | SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs), | 496 | SND_SOC_FSBD_REAL(rtd->cpu_dai->dai_runtime.bfs), |
545 | bclk, | 497 | clk_get_rate(mck_clk) / (2 * div), |
546 | div, | 498 | div, |
547 | period); | 499 | period); |
548 | 500 | ||
549 | clk_put(mck_clk); | 501 | clk_put(mck_clk); |
550 | 502 | ||
551 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_CMR, div); | 503 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, div); |
552 | 504 | ||
553 | /* | 505 | /* |
554 | * Setup the TFMR and RFMR for the proper data format. | 506 | * Setup the TFMR and RFMR for the proper data format. |
@@ -563,7 +515,7 @@ static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | |||
563 | | (( 0 << 5) & AT91_SSC_DATDEF) | 515 | | (( 0 << 5) & AT91_SSC_DATDEF) |
564 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | 516 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); |
565 | DBG("SSC_TFMR=0x%08x\n", tfmr); | 517 | DBG("SSC_TFMR=0x%08x\n", tfmr); |
566 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_TFMR, tfmr); | 518 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr); |
567 | 519 | ||
568 | rfmr = | 520 | rfmr = |
569 | (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | 521 | (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) |
@@ -575,7 +527,7 @@ static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | |||
575 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | 527 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); |
576 | 528 | ||
577 | DBG("SSC_RFMR=0x%08x\n", rfmr); | 529 | DBG("SSC_RFMR=0x%08x\n", rfmr); |
578 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RFMR, rfmr); | 530 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr); |
579 | 531 | ||
580 | /* | 532 | /* |
581 | * Setup the TCMR and RCMR to generate the proper BCLK | 533 | * Setup the TCMR and RCMR to generate the proper BCLK |
@@ -590,7 +542,7 @@ static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | |||
590 | | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); | 542 | | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); |
591 | 543 | ||
592 | DBG("SSC_TCMR=0x%08x\n", tcmr); | 544 | DBG("SSC_TCMR=0x%08x\n", tcmr); |
593 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_TCMR, tcmr); | 545 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr); |
594 | 546 | ||
595 | rcmr = | 547 | rcmr = |
596 | (( 0 << 24) & AT91_SSC_PERIOD) | 548 | (( 0 << 24) & AT91_SSC_PERIOD) |
@@ -601,11 +553,11 @@ static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | |||
601 | | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS); | 553 | | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS); |
602 | 554 | ||
603 | DBG("SSC_RCMR=0x%08x\n", rcmr); | 555 | DBG("SSC_RCMR=0x%08x\n", rcmr); |
604 | at91_ssc_write(ssc_p->ssc_base + AT91_SSC_RCMR, rcmr); | 556 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr); |
605 | 557 | ||
606 | if ((ret = request_irq(ssc_p->pid, at91rm9200_i2s_interrupt, | 558 | if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt, |
607 | 0, ssc_p->name, ssc_p)) < 0) { | 559 | 0, ssc_p->name, ssc_p)) < 0) { |
608 | printk(KERN_WARNING "at91rm9200-i2s: request_irq failure\n"); | 560 | printk(KERN_WARNING "at91-i2s: request_irq failure\n"); |
609 | return ret; | 561 | return ret; |
610 | } | 562 | } |
611 | 563 | ||
@@ -627,27 +579,28 @@ static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, | |||
627 | } | 579 | } |
628 | 580 | ||
629 | 581 | ||
630 | static int at91rm9200_i2s_prepare(struct snd_pcm_substream *substream) | 582 | static int at91_i2s_prepare(struct snd_pcm_substream *substream) |
631 | { | 583 | { |
632 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 584 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
633 | at91rm9200_pcm_dma_params_t *dma_params = rtd->cpu_dai->dma_data; | 585 | struct at91_pcm_dma_params *dma_params = rtd->cpu_dai->dma_data; |
634 | 586 | ||
635 | at91_ssc_write(dma_params->ssc->cr, dma_params->mask->ssc_enable); | 587 | at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR, |
588 | dma_params->mask->ssc_enable); | ||
636 | 589 | ||
637 | DBG("%s enabled SSC_SR=0x%08lx\n", | 590 | DBG("%s enabled SSC_SR=0x%08lx\n", |
638 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "transmit" : "receive", | 591 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "transmit" : "receive", |
639 | at91_ssc_read(ssc_info[rtd->cpu_dai->id].ssc_base + AT91_SSC_SR)); | 592 | at91_ssc_read(ssc_info[rtd->cpu_dai->id].ssc.base + AT91_SSC_SR)); |
640 | return 0; | 593 | return 0; |
641 | } | 594 | } |
642 | 595 | ||
643 | 596 | ||
644 | struct snd_soc_cpu_dai at91rm9200_i2s_dai[] = { | 597 | struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = { |
645 | { .name = "at91rm9200-ssc0/i2s", | 598 | { .name = "at91_ssc0/i2s", |
646 | .id = 0, | 599 | .id = 0, |
647 | .type = SND_SOC_DAI_I2S, | 600 | .type = SND_SOC_DAI_I2S, |
648 | .suspend = at91rm9200_i2s_suspend, | 601 | .suspend = at91_i2s_suspend, |
649 | .resume = at91rm9200_i2s_resume, | 602 | .resume = at91_i2s_resume, |
650 | .config_sysclk = at91rm9200_i2s_config_sysclk, | 603 | .config_sysclk = at91_i2s_config_sysclk, |
651 | .playback = { | 604 | .playback = { |
652 | .channels_min = 1, | 605 | .channels_min = 1, |
653 | .channels_max = 2,}, | 606 | .channels_max = 2,}, |
@@ -655,20 +608,22 @@ struct snd_soc_cpu_dai at91rm9200_i2s_dai[] = { | |||
655 | .channels_min = 1, | 608 | .channels_min = 1, |
656 | .channels_max = 2,}, | 609 | .channels_max = 2,}, |
657 | .ops = { | 610 | .ops = { |
658 | .startup = at91rm9200_i2s_startup, | 611 | .startup = at91_i2s_startup, |
659 | .shutdown = at91rm9200_i2s_shutdown, | 612 | .shutdown = at91_i2s_shutdown, |
660 | .prepare = at91rm9200_i2s_prepare, | 613 | .prepare = at91_i2s_prepare, |
661 | .hw_params = at91rm9200_i2s_hw_params,}, | 614 | .hw_params = at91_i2s_hw_params,}, |
662 | .caps = { | 615 | .caps = { |
663 | .mode = &at91rm9200_i2s[0], | 616 | .mode = &at91_i2s[0], |
664 | .num_modes = ARRAY_SIZE(at91rm9200_i2s),}, | 617 | .num_modes = ARRAY_SIZE(at91_i2s),}, |
618 | .private_data = &ssc_info[0].ssc, | ||
665 | }, | 619 | }, |
666 | { .name = "at91rm9200-ssc1/i2s", | 620 | #if NUM_SSC_DEVICES == 3 |
621 | { .name = "at91_ssc1/i2s", | ||
667 | .id = 1, | 622 | .id = 1, |
668 | .type = SND_SOC_DAI_I2S, | 623 | .type = SND_SOC_DAI_I2S, |
669 | .suspend = at91rm9200_i2s_suspend, | 624 | .suspend = at91_i2s_suspend, |
670 | .resume = at91rm9200_i2s_resume, | 625 | .resume = at91_i2s_resume, |
671 | .config_sysclk = at91rm9200_i2s_config_sysclk, | 626 | .config_sysclk = at91_i2s_config_sysclk, |
672 | .playback = { | 627 | .playback = { |
673 | .channels_min = 1, | 628 | .channels_min = 1, |
674 | .channels_max = 2,}, | 629 | .channels_max = 2,}, |
@@ -676,20 +631,21 @@ struct snd_soc_cpu_dai at91rm9200_i2s_dai[] = { | |||
676 | .channels_min = 1, | 631 | .channels_min = 1, |
677 | .channels_max = 2,}, | 632 | .channels_max = 2,}, |
678 | .ops = { | 633 | .ops = { |
679 | .startup = at91rm9200_i2s_startup, | 634 | .startup = at91_i2s_startup, |
680 | .shutdown = at91rm9200_i2s_shutdown, | 635 | .shutdown = at91_i2s_shutdown, |
681 | .prepare = at91rm9200_i2s_prepare, | 636 | .prepare = at91_i2s_prepare, |
682 | .hw_params = at91rm9200_i2s_hw_params,}, | 637 | .hw_params = at91_i2s_hw_params,}, |
683 | .caps = { | 638 | .caps = { |
684 | .mode = &at91rm9200_i2s[0], | 639 | .mode = &at91_i2s[0], |
685 | .num_modes = ARRAY_SIZE(at91rm9200_i2s),}, | 640 | .num_modes = ARRAY_SIZE(at91_i2s),}, |
641 | .private_data = &ssc_info[1].ssc, | ||
686 | }, | 642 | }, |
687 | { .name = "at91rm9200-ssc2/i2s", | 643 | { .name = "at91_ssc2/i2s", |
688 | .id = 2, | 644 | .id = 2, |
689 | .type = SND_SOC_DAI_I2S, | 645 | .type = SND_SOC_DAI_I2S, |
690 | .suspend = at91rm9200_i2s_suspend, | 646 | .suspend = at91_i2s_suspend, |
691 | .resume = at91rm9200_i2s_resume, | 647 | .resume = at91_i2s_resume, |
692 | .config_sysclk = at91rm9200_i2s_config_sysclk, | 648 | .config_sysclk = at91_i2s_config_sysclk, |
693 | .playback = { | 649 | .playback = { |
694 | .channels_min = 1, | 650 | .channels_min = 1, |
695 | .channels_max = 2,}, | 651 | .channels_max = 2,}, |
@@ -697,19 +653,21 @@ struct snd_soc_cpu_dai at91rm9200_i2s_dai[] = { | |||
697 | .channels_min = 1, | 653 | .channels_min = 1, |
698 | .channels_max = 2,}, | 654 | .channels_max = 2,}, |
699 | .ops = { | 655 | .ops = { |
700 | .startup = at91rm9200_i2s_startup, | 656 | .startup = at91_i2s_startup, |
701 | .shutdown = at91rm9200_i2s_shutdown, | 657 | .shutdown = at91_i2s_shutdown, |
702 | .prepare = at91rm9200_i2s_prepare, | 658 | .prepare = at91_i2s_prepare, |
703 | .hw_params = at91rm9200_i2s_hw_params,}, | 659 | .hw_params = at91_i2s_hw_params,}, |
704 | .caps = { | 660 | .caps = { |
705 | .mode = &at91rm9200_i2s[0], | 661 | .mode = &at91_i2s[0], |
706 | .num_modes = ARRAY_SIZE(at91rm9200_i2s),}, | 662 | .num_modes = ARRAY_SIZE(at91_i2s),}, |
663 | .private_data = &ssc_info[2].ssc, | ||
707 | }, | 664 | }, |
665 | #endif | ||
708 | }; | 666 | }; |
709 | 667 | ||
710 | EXPORT_SYMBOL_GPL(at91rm9200_i2s_dai); | 668 | EXPORT_SYMBOL_GPL(at91_i2s_dai); |
711 | 669 | ||
712 | /* Module information */ | 670 | /* Module information */ |
713 | MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com"); | 671 | MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com"); |
714 | MODULE_DESCRIPTION("AT91RM9200 I2S ASoC Interface"); | 672 | MODULE_DESCRIPTION("AT91 I2S ASoC Interface"); |
715 | MODULE_LICENSE("GPL"); | 673 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/at91/at91rm9200-pcm.c b/sound/soc/at91/at91-pcm.c index 237bc5f07579..fd9d7327b239 100644 --- a/sound/soc/at91/at91rm9200-pcm.c +++ b/sound/soc/at91/at91-pcm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * at91rm9200-pcm.c -- ALSA PCM interface for the Atmel AT91RM9200 chip. | 2 | * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC |
3 | * | 3 | * |
4 | * Author: Frank Mandarino <fmandarino@endrelia.com> | 4 | * Author: Frank Mandarino <fmandarino@endrelia.com> |
5 | * Endrelia Technologies Inc. | 5 | * Endrelia Technologies Inc. |
@@ -28,20 +28,19 @@ | |||
28 | #include <sound/pcm_params.h> | 28 | #include <sound/pcm_params.h> |
29 | #include <sound/soc.h> | 29 | #include <sound/soc.h> |
30 | 30 | ||
31 | #include <asm/arch/at91rm9200.h> | ||
32 | #include <asm/arch/at91rm9200_ssc.h> | ||
33 | #include <asm/arch/at91rm9200_pdc.h> | ||
34 | #include <asm/arch/hardware.h> | 31 | #include <asm/arch/hardware.h> |
32 | #include <asm/arch/at91_ssc.h> | ||
33 | #include <asm/arch/at91_pdc.h> | ||
35 | 34 | ||
36 | #include "at91rm9200-pcm.h" | 35 | #include "at91-pcm.h" |
37 | 36 | ||
38 | #if 0 | 37 | #if 0 |
39 | #define DBG(x...) printk(KERN_INFO "at91rm9200-pcm: " x) | 38 | #define DBG(x...) printk(KERN_INFO "at91-pcm: " x) |
40 | #else | 39 | #else |
41 | #define DBG(x...) | 40 | #define DBG(x...) |
42 | #endif | 41 | #endif |
43 | 42 | ||
44 | static const snd_pcm_hardware_t at91rm9200_pcm_hardware = { | 43 | static const struct snd_pcm_hardware at91_pcm_hardware = { |
45 | .info = SNDRV_PCM_INFO_MMAP | | 44 | .info = SNDRV_PCM_INFO_MMAP | |
46 | SNDRV_PCM_INFO_MMAP_VALID | | 45 | SNDRV_PCM_INFO_MMAP_VALID | |
47 | SNDRV_PCM_INFO_INTERLEAVED | | 46 | SNDRV_PCM_INFO_INTERLEAVED | |
@@ -54,8 +53,8 @@ static const snd_pcm_hardware_t at91rm9200_pcm_hardware = { | |||
54 | .buffer_bytes_max = 32 * 1024, | 53 | .buffer_bytes_max = 32 * 1024, |
55 | }; | 54 | }; |
56 | 55 | ||
57 | struct at91rm9200_runtime_data { | 56 | struct at91_runtime_data { |
58 | at91rm9200_pcm_dma_params_t *params; | 57 | struct at91_pcm_dma_params *params; |
59 | dma_addr_t dma_buffer; /* physical address of dma buffer */ | 58 | dma_addr_t dma_buffer; /* physical address of dma buffer */ |
60 | dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */ | 59 | dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */ |
61 | size_t period_size; | 60 | size_t period_size; |
@@ -66,11 +65,11 @@ struct at91rm9200_runtime_data { | |||
66 | u32 pdc_xncr_save; | 65 | u32 pdc_xncr_save; |
67 | }; | 66 | }; |
68 | 67 | ||
69 | static void at91rm9200_pcm_dma_irq(u32 ssc_sr, | 68 | static void at91_pcm_dma_irq(u32 ssc_sr, |
70 | struct snd_pcm_substream *substream) | 69 | struct snd_pcm_substream *substream) |
71 | { | 70 | { |
72 | struct at91rm9200_runtime_data *prtd = substream->runtime->private_data; | 71 | struct at91_runtime_data *prtd = substream->runtime->private_data; |
73 | at91rm9200_pcm_dma_params_t *params = prtd->params; | 72 | struct at91_pcm_dma_params *params = prtd->params; |
74 | static int count = 0; | 73 | static int count = 0; |
75 | 74 | ||
76 | count++; | 75 | count++; |
@@ -78,24 +77,24 @@ static void at91rm9200_pcm_dma_irq(u32 ssc_sr, | |||
78 | if (ssc_sr & params->mask->ssc_endbuf) { | 77 | if (ssc_sr & params->mask->ssc_endbuf) { |
79 | 78 | ||
80 | printk(KERN_WARNING | 79 | printk(KERN_WARNING |
81 | "at91rm9200-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n", | 80 | "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n", |
82 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK | 81 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK |
83 | ? "underrun" : "overrun", | 82 | ? "underrun" : "overrun", |
84 | params->name, ssc_sr, count); | 83 | params->name, ssc_sr, count); |
85 | 84 | ||
86 | /* re-start the PDC */ | 85 | /* re-start the PDC */ |
87 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable); | 86 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable); |
88 | 87 | ||
89 | prtd->period_ptr += prtd->period_size; | 88 | prtd->period_ptr += prtd->period_size; |
90 | if (prtd->period_ptr >= prtd->dma_buffer_end) { | 89 | if (prtd->period_ptr >= prtd->dma_buffer_end) { |
91 | prtd->period_ptr = prtd->dma_buffer; | 90 | prtd->period_ptr = prtd->dma_buffer; |
92 | } | 91 | } |
93 | 92 | ||
94 | at91_ssc_write(params->pdc->xpr, prtd->period_ptr); | 93 | at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr); |
95 | at91_ssc_write(params->pdc->xcr, | 94 | at91_ssc_write(params->ssc_base + params->pdc->xcr, |
96 | prtd->period_size / params->pdc_xfer_size); | 95 | prtd->period_size / params->pdc_xfer_size); |
97 | 96 | ||
98 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_enable); | 97 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable); |
99 | } | 98 | } |
100 | 99 | ||
101 | if (ssc_sr & params->mask->ssc_endx) { | 100 | if (ssc_sr & params->mask->ssc_endx) { |
@@ -105,19 +104,19 @@ static void at91rm9200_pcm_dma_irq(u32 ssc_sr, | |||
105 | if (prtd->period_ptr >= prtd->dma_buffer_end) { | 104 | if (prtd->period_ptr >= prtd->dma_buffer_end) { |
106 | prtd->period_ptr = prtd->dma_buffer; | 105 | prtd->period_ptr = prtd->dma_buffer; |
107 | } | 106 | } |
108 | at91_ssc_write(params->pdc->xnpr, prtd->period_ptr); | 107 | at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr); |
109 | at91_ssc_write(params->pdc->xncr, | 108 | at91_ssc_write(params->ssc_base + params->pdc->xncr, |
110 | prtd->period_size / params->pdc_xfer_size); | 109 | prtd->period_size / params->pdc_xfer_size); |
111 | } | 110 | } |
112 | 111 | ||
113 | snd_pcm_period_elapsed(substream); | 112 | snd_pcm_period_elapsed(substream); |
114 | } | 113 | } |
115 | 114 | ||
116 | static int at91rm9200_pcm_hw_params(struct snd_pcm_substream *substream, | 115 | static int at91_pcm_hw_params(struct snd_pcm_substream *substream, |
117 | struct snd_pcm_hw_params *params) | 116 | struct snd_pcm_hw_params *params) |
118 | { | 117 | { |
119 | snd_pcm_runtime_t *runtime = substream->runtime; | 118 | struct snd_pcm_runtime *runtime = substream->runtime; |
120 | struct at91rm9200_runtime_data *prtd = runtime->private_data; | 119 | struct at91_runtime_data *prtd = runtime->private_data; |
121 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 120 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
122 | 121 | ||
123 | /* this may get called several times by oss emulation | 122 | /* this may get called several times by oss emulation |
@@ -127,7 +126,7 @@ static int at91rm9200_pcm_hw_params(struct snd_pcm_substream *substream, | |||
127 | runtime->dma_bytes = params_buffer_bytes(params); | 126 | runtime->dma_bytes = params_buffer_bytes(params); |
128 | 127 | ||
129 | prtd->params = rtd->cpu_dai->dma_data; | 128 | prtd->params = rtd->cpu_dai->dma_data; |
130 | prtd->params->dma_intr_handler = at91rm9200_pcm_dma_irq; | 129 | prtd->params->dma_intr_handler = at91_pcm_dma_irq; |
131 | 130 | ||
132 | prtd->dma_buffer = runtime->dma_addr; | 131 | prtd->dma_buffer = runtime->dma_addr; |
133 | prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; | 132 | prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; |
@@ -138,76 +137,76 @@ static int at91rm9200_pcm_hw_params(struct snd_pcm_substream *substream, | |||
138 | return 0; | 137 | return 0; |
139 | } | 138 | } |
140 | 139 | ||
141 | static int at91rm9200_pcm_hw_free(struct snd_pcm_substream *substream) | 140 | static int at91_pcm_hw_free(struct snd_pcm_substream *substream) |
142 | { | 141 | { |
143 | struct at91rm9200_runtime_data *prtd = substream->runtime->private_data; | 142 | struct at91_runtime_data *prtd = substream->runtime->private_data; |
144 | at91rm9200_pcm_dma_params_t *params = prtd->params; | 143 | struct at91_pcm_dma_params *params = prtd->params; |
145 | 144 | ||
146 | if (params != NULL) { | 145 | if (params != NULL) { |
147 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable); | 146 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable); |
148 | prtd->params->dma_intr_handler = NULL; | 147 | prtd->params->dma_intr_handler = NULL; |
149 | } | 148 | } |
150 | 149 | ||
151 | return 0; | 150 | return 0; |
152 | } | 151 | } |
153 | 152 | ||
154 | static int at91rm9200_pcm_prepare(struct snd_pcm_substream *substream) | 153 | static int at91_pcm_prepare(struct snd_pcm_substream *substream) |
155 | { | 154 | { |
156 | struct at91rm9200_runtime_data *prtd = substream->runtime->private_data; | 155 | struct at91_runtime_data *prtd = substream->runtime->private_data; |
157 | at91rm9200_pcm_dma_params_t *params = prtd->params; | 156 | struct at91_pcm_dma_params *params = prtd->params; |
158 | 157 | ||
159 | at91_ssc_write(params->ssc->idr, | 158 | at91_ssc_write(params->ssc_base + AT91_SSC_IDR, |
160 | params->mask->ssc_endx | params->mask->ssc_endbuf); | 159 | params->mask->ssc_endx | params->mask->ssc_endbuf); |
161 | 160 | ||
162 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable); | 161 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable); |
163 | return 0; | 162 | return 0; |
164 | } | 163 | } |
165 | 164 | ||
166 | static int at91rm9200_pcm_trigger(struct snd_pcm_substream *substream, | 165 | static int at91_pcm_trigger(struct snd_pcm_substream *substream, |
167 | int cmd) | 166 | int cmd) |
168 | { | 167 | { |
169 | struct at91rm9200_runtime_data *prtd = substream->runtime->private_data; | 168 | struct at91_runtime_data *prtd = substream->runtime->private_data; |
170 | at91rm9200_pcm_dma_params_t *params = prtd->params; | 169 | struct at91_pcm_dma_params *params = prtd->params; |
171 | int ret = 0; | 170 | int ret = 0; |
172 | 171 | ||
173 | switch (cmd) { | 172 | switch (cmd) { |
174 | case SNDRV_PCM_TRIGGER_START: | 173 | case SNDRV_PCM_TRIGGER_START: |
175 | prtd->period_ptr = prtd->dma_buffer; | 174 | prtd->period_ptr = prtd->dma_buffer; |
176 | 175 | ||
177 | at91_ssc_write(params->pdc->xpr, prtd->period_ptr); | 176 | at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr); |
178 | at91_ssc_write(params->pdc->xcr, | 177 | at91_ssc_write(params->ssc_base + params->pdc->xcr, |
179 | prtd->period_size / params->pdc_xfer_size); | 178 | prtd->period_size / params->pdc_xfer_size); |
180 | 179 | ||
181 | prtd->period_ptr += prtd->period_size; | 180 | prtd->period_ptr += prtd->period_size; |
182 | at91_ssc_write(params->pdc->xnpr, prtd->period_ptr); | 181 | at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr); |
183 | at91_ssc_write(params->pdc->xncr, | 182 | at91_ssc_write(params->ssc_base + params->pdc->xncr, |
184 | prtd->period_size / params->pdc_xfer_size); | 183 | prtd->period_size / params->pdc_xfer_size); |
185 | 184 | ||
186 | DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n", | 185 | DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n", |
187 | (unsigned long) prtd->period_ptr, | 186 | (unsigned long) prtd->period_ptr, |
188 | at91_ssc_read(params->pdc->xpr), | 187 | at91_ssc_read(params->ssc_base + params->pdc->xpr), |
189 | at91_ssc_read(params->pdc->xcr), | 188 | at91_ssc_read(params->ssc_base + params->pdc->xcr), |
190 | at91_ssc_read(params->pdc->xnpr), | 189 | at91_ssc_read(params->ssc_base + params->pdc->xnpr), |
191 | at91_ssc_read(params->pdc->xncr)); | 190 | at91_ssc_read(params->ssc_base + params->pdc->xncr)); |
192 | 191 | ||
193 | at91_ssc_write(params->ssc->ier, | 192 | at91_ssc_write(params->ssc_base + AT91_SSC_IER, |
194 | params->mask->ssc_endx | params->mask->ssc_endbuf); | 193 | params->mask->ssc_endx | params->mask->ssc_endbuf); |
195 | 194 | ||
196 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_enable); | 195 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable); |
197 | 196 | ||
198 | DBG("sr=%lx imr=%lx\n", at91_ssc_read(params->ssc->ier - 4), | 197 | DBG("sr=%lx imr=%lx\n", at91_ssc_read(params->ssc_base + AT91_SSC_SR), |
199 | at91_ssc_read(params->ssc->ier + 8)); | 198 | at91_ssc_read(params->ssc_base + AT91_SSC_IER)); |
200 | break; | 199 | break; |
201 | 200 | ||
202 | case SNDRV_PCM_TRIGGER_STOP: | 201 | case SNDRV_PCM_TRIGGER_STOP: |
203 | case SNDRV_PCM_TRIGGER_SUSPEND: | 202 | case SNDRV_PCM_TRIGGER_SUSPEND: |
204 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 203 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
205 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable); | 204 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable); |
206 | break; | 205 | break; |
207 | 206 | ||
208 | case SNDRV_PCM_TRIGGER_RESUME: | 207 | case SNDRV_PCM_TRIGGER_RESUME: |
209 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 208 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
210 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_enable); | 209 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable); |
211 | break; | 210 | break; |
212 | 211 | ||
213 | default: | 212 | default: |
@@ -217,16 +216,16 @@ static int at91rm9200_pcm_trigger(struct snd_pcm_substream *substream, | |||
217 | return ret; | 216 | return ret; |
218 | } | 217 | } |
219 | 218 | ||
220 | static snd_pcm_uframes_t at91rm9200_pcm_pointer( | 219 | static snd_pcm_uframes_t at91_pcm_pointer( |
221 | struct snd_pcm_substream *substream) | 220 | struct snd_pcm_substream *substream) |
222 | { | 221 | { |
223 | struct snd_pcm_runtime *runtime = substream->runtime; | 222 | struct snd_pcm_runtime *runtime = substream->runtime; |
224 | struct at91rm9200_runtime_data *prtd = runtime->private_data; | 223 | struct at91_runtime_data *prtd = runtime->private_data; |
225 | at91rm9200_pcm_dma_params_t *params = prtd->params; | 224 | struct at91_pcm_dma_params *params = prtd->params; |
226 | dma_addr_t ptr; | 225 | dma_addr_t ptr; |
227 | snd_pcm_uframes_t x; | 226 | snd_pcm_uframes_t x; |
228 | 227 | ||
229 | ptr = (dma_addr_t) at91_ssc_read(params->pdc->xpr); | 228 | ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr); |
230 | x = bytes_to_frames(runtime, ptr - prtd->dma_buffer); | 229 | x = bytes_to_frames(runtime, ptr - prtd->dma_buffer); |
231 | 230 | ||
232 | if (x == runtime->buffer_size) | 231 | if (x == runtime->buffer_size) |
@@ -234,20 +233,20 @@ static snd_pcm_uframes_t at91rm9200_pcm_pointer( | |||
234 | return x; | 233 | return x; |
235 | } | 234 | } |
236 | 235 | ||
237 | static int at91rm9200_pcm_open(struct snd_pcm_substream *substream) | 236 | static int at91_pcm_open(struct snd_pcm_substream *substream) |
238 | { | 237 | { |
239 | struct snd_pcm_runtime *runtime = substream->runtime; | 238 | struct snd_pcm_runtime *runtime = substream->runtime; |
240 | struct at91rm9200_runtime_data *prtd; | 239 | struct at91_runtime_data *prtd; |
241 | int ret = 0; | 240 | int ret = 0; |
242 | 241 | ||
243 | snd_soc_set_runtime_hwparams(substream, &at91rm9200_pcm_hardware); | 242 | snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware); |
244 | 243 | ||
245 | /* ensure that buffer size is a multiple of period size */ | 244 | /* ensure that buffer size is a multiple of period size */ |
246 | ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | 245 | ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); |
247 | if (ret < 0) | 246 | if (ret < 0) |
248 | goto out; | 247 | goto out; |
249 | 248 | ||
250 | prtd = kzalloc(sizeof(struct at91rm9200_runtime_data), GFP_KERNEL); | 249 | prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL); |
251 | if (prtd == NULL) { | 250 | if (prtd == NULL) { |
252 | ret = -ENOMEM; | 251 | ret = -ENOMEM; |
253 | goto out; | 252 | goto out; |
@@ -258,15 +257,15 @@ static int at91rm9200_pcm_open(struct snd_pcm_substream *substream) | |||
258 | return ret; | 257 | return ret; |
259 | } | 258 | } |
260 | 259 | ||
261 | static int at91rm9200_pcm_close(struct snd_pcm_substream *substream) | 260 | static int at91_pcm_close(struct snd_pcm_substream *substream) |
262 | { | 261 | { |
263 | struct at91rm9200_runtime_data *prtd = substream->runtime->private_data; | 262 | struct at91_runtime_data *prtd = substream->runtime->private_data; |
264 | 263 | ||
265 | kfree(prtd); | 264 | kfree(prtd); |
266 | return 0; | 265 | return 0; |
267 | } | 266 | } |
268 | 267 | ||
269 | static int at91rm9200_pcm_mmap(struct snd_pcm_substream *substream, | 268 | static int at91_pcm_mmap(struct snd_pcm_substream *substream, |
270 | struct vm_area_struct *vma) | 269 | struct vm_area_struct *vma) |
271 | { | 270 | { |
272 | struct snd_pcm_runtime *runtime = substream->runtime; | 271 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -277,24 +276,24 @@ static int at91rm9200_pcm_mmap(struct snd_pcm_substream *substream, | |||
277 | runtime->dma_bytes); | 276 | runtime->dma_bytes); |
278 | } | 277 | } |
279 | 278 | ||
280 | struct snd_pcm_ops at91rm9200_pcm_ops = { | 279 | struct snd_pcm_ops at91_pcm_ops = { |
281 | .open = at91rm9200_pcm_open, | 280 | .open = at91_pcm_open, |
282 | .close = at91rm9200_pcm_close, | 281 | .close = at91_pcm_close, |
283 | .ioctl = snd_pcm_lib_ioctl, | 282 | .ioctl = snd_pcm_lib_ioctl, |
284 | .hw_params = at91rm9200_pcm_hw_params, | 283 | .hw_params = at91_pcm_hw_params, |
285 | .hw_free = at91rm9200_pcm_hw_free, | 284 | .hw_free = at91_pcm_hw_free, |
286 | .prepare = at91rm9200_pcm_prepare, | 285 | .prepare = at91_pcm_prepare, |
287 | .trigger = at91rm9200_pcm_trigger, | 286 | .trigger = at91_pcm_trigger, |
288 | .pointer = at91rm9200_pcm_pointer, | 287 | .pointer = at91_pcm_pointer, |
289 | .mmap = at91rm9200_pcm_mmap, | 288 | .mmap = at91_pcm_mmap, |
290 | }; | 289 | }; |
291 | 290 | ||
292 | static int at91rm9200_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, | 291 | static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, |
293 | int stream) | 292 | int stream) |
294 | { | 293 | { |
295 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | 294 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; |
296 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 295 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
297 | size_t size = at91rm9200_pcm_hardware.buffer_bytes_max; | 296 | size_t size = at91_pcm_hardware.buffer_bytes_max; |
298 | 297 | ||
299 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | 298 | buf->dev.type = SNDRV_DMA_TYPE_DEV; |
300 | buf->dev.dev = pcm->card->dev; | 299 | buf->dev.dev = pcm->card->dev; |
@@ -314,27 +313,27 @@ static int at91rm9200_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, | |||
314 | return 0; | 313 | return 0; |
315 | } | 314 | } |
316 | 315 | ||
317 | static u64 at91rm9200_pcm_dmamask = 0xffffffff; | 316 | static u64 at91_pcm_dmamask = 0xffffffff; |
318 | 317 | ||
319 | static int at91rm9200_pcm_new(struct snd_card *card, | 318 | static int at91_pcm_new(struct snd_card *card, |
320 | struct snd_soc_codec_dai *dai, struct snd_pcm *pcm) | 319 | struct snd_soc_codec_dai *dai, struct snd_pcm *pcm) |
321 | { | 320 | { |
322 | int ret = 0; | 321 | int ret = 0; |
323 | 322 | ||
324 | if (!card->dev->dma_mask) | 323 | if (!card->dev->dma_mask) |
325 | card->dev->dma_mask = &at91rm9200_pcm_dmamask; | 324 | card->dev->dma_mask = &at91_pcm_dmamask; |
326 | if (!card->dev->coherent_dma_mask) | 325 | if (!card->dev->coherent_dma_mask) |
327 | card->dev->coherent_dma_mask = 0xffffffff; | 326 | card->dev->coherent_dma_mask = 0xffffffff; |
328 | 327 | ||
329 | if (dai->playback.channels_min) { | 328 | if (dai->playback.channels_min) { |
330 | ret = at91rm9200_pcm_preallocate_dma_buffer(pcm, | 329 | ret = at91_pcm_preallocate_dma_buffer(pcm, |
331 | SNDRV_PCM_STREAM_PLAYBACK); | 330 | SNDRV_PCM_STREAM_PLAYBACK); |
332 | if (ret) | 331 | if (ret) |
333 | goto out; | 332 | goto out; |
334 | } | 333 | } |
335 | 334 | ||
336 | if (dai->capture.channels_min) { | 335 | if (dai->capture.channels_min) { |
337 | ret = at91rm9200_pcm_preallocate_dma_buffer(pcm, | 336 | ret = at91_pcm_preallocate_dma_buffer(pcm, |
338 | SNDRV_PCM_STREAM_CAPTURE); | 337 | SNDRV_PCM_STREAM_CAPTURE); |
339 | if (ret) | 338 | if (ret) |
340 | goto out; | 339 | goto out; |
@@ -343,7 +342,7 @@ static int at91rm9200_pcm_new(struct snd_card *card, | |||
343 | return ret; | 342 | return ret; |
344 | } | 343 | } |
345 | 344 | ||
346 | static void at91rm9200_pcm_free_dma_buffers(struct snd_pcm *pcm) | 345 | static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm) |
347 | { | 346 | { |
348 | struct snd_pcm_substream *substream; | 347 | struct snd_pcm_substream *substream; |
349 | struct snd_dma_buffer *buf; | 348 | struct snd_dma_buffer *buf; |
@@ -364,12 +363,12 @@ static void at91rm9200_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
364 | } | 363 | } |
365 | } | 364 | } |
366 | 365 | ||
367 | static int at91rm9200_pcm_suspend(struct platform_device *pdev, | 366 | static int at91_pcm_suspend(struct platform_device *pdev, |
368 | struct snd_soc_cpu_dai *dai) | 367 | struct snd_soc_cpu_dai *dai) |
369 | { | 368 | { |
370 | struct snd_pcm_runtime *runtime = dai->runtime; | 369 | struct snd_pcm_runtime *runtime = dai->runtime; |
371 | struct at91rm9200_runtime_data *prtd; | 370 | struct at91_runtime_data *prtd; |
372 | at91rm9200_pcm_dma_params_t *params; | 371 | struct at91_pcm_dma_params *params; |
373 | 372 | ||
374 | if (!runtime) | 373 | if (!runtime) |
375 | return 0; | 374 | return 0; |
@@ -379,22 +378,22 @@ static int at91rm9200_pcm_suspend(struct platform_device *pdev, | |||
379 | 378 | ||
380 | /* disable the PDC and save the PDC registers */ | 379 | /* disable the PDC and save the PDC registers */ |
381 | 380 | ||
382 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_disable); | 381 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable); |
383 | 382 | ||
384 | prtd->pdc_xpr_save = at91_ssc_read(params->pdc->xpr); | 383 | prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr); |
385 | prtd->pdc_xcr_save = at91_ssc_read(params->pdc->xcr); | 384 | prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr); |
386 | prtd->pdc_xnpr_save = at91_ssc_read(params->pdc->xnpr); | 385 | prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr); |
387 | prtd->pdc_xncr_save = at91_ssc_read(params->pdc->xncr); | 386 | prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr); |
388 | 387 | ||
389 | return 0; | 388 | return 0; |
390 | } | 389 | } |
391 | 390 | ||
392 | static int at91rm9200_pcm_resume(struct platform_device *pdev, | 391 | static int at91_pcm_resume(struct platform_device *pdev, |
393 | struct snd_soc_cpu_dai *dai) | 392 | struct snd_soc_cpu_dai *dai) |
394 | { | 393 | { |
395 | struct snd_pcm_runtime *runtime = dai->runtime; | 394 | struct snd_pcm_runtime *runtime = dai->runtime; |
396 | struct at91rm9200_runtime_data *prtd; | 395 | struct at91_runtime_data *prtd; |
397 | at91rm9200_pcm_dma_params_t *params; | 396 | struct at91_pcm_dma_params *params; |
398 | 397 | ||
399 | if (!runtime) | 398 | if (!runtime) |
400 | return 0; | 399 | return 0; |
@@ -403,26 +402,26 @@ static int at91rm9200_pcm_resume(struct platform_device *pdev, | |||
403 | params = prtd->params; | 402 | params = prtd->params; |
404 | 403 | ||
405 | /* restore the PDC registers and enable the PDC */ | 404 | /* restore the PDC registers and enable the PDC */ |
406 | at91_ssc_write(params->pdc->xpr, prtd->pdc_xpr_save); | 405 | at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save); |
407 | at91_ssc_write(params->pdc->xcr, prtd->pdc_xcr_save); | 406 | at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save); |
408 | at91_ssc_write(params->pdc->xnpr, prtd->pdc_xnpr_save); | 407 | at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save); |
409 | at91_ssc_write(params->pdc->xncr, prtd->pdc_xncr_save); | 408 | at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save); |
410 | 409 | ||
411 | at91_ssc_write(params->pdc->ptcr, params->mask->pdc_enable); | 410 | at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable); |
412 | return 0; | 411 | return 0; |
413 | } | 412 | } |
414 | 413 | ||
415 | struct snd_soc_platform at91rm9200_soc_platform = { | 414 | struct snd_soc_platform at91_soc_platform = { |
416 | .name = "at91rm9200-audio", | 415 | .name = "at91-audio", |
417 | .pcm_ops = &at91rm9200_pcm_ops, | 416 | .pcm_ops = &at91_pcm_ops, |
418 | .pcm_new = at91rm9200_pcm_new, | 417 | .pcm_new = at91_pcm_new, |
419 | .pcm_free = at91rm9200_pcm_free_dma_buffers, | 418 | .pcm_free = at91_pcm_free_dma_buffers, |
420 | .suspend = at91rm9200_pcm_suspend, | 419 | .suspend = at91_pcm_suspend, |
421 | .resume = at91rm9200_pcm_resume, | 420 | .resume = at91_pcm_resume, |
422 | }; | 421 | }; |
423 | 422 | ||
424 | EXPORT_SYMBOL_GPL(at91rm9200_soc_platform); | 423 | EXPORT_SYMBOL_GPL(at91_soc_platform); |
425 | 424 | ||
426 | MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>"); | 425 | MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>"); |
427 | MODULE_DESCRIPTION("Atmel AT91RM9200 PCM module"); | 426 | MODULE_DESCRIPTION("Atmel AT91 PCM module"); |
428 | MODULE_LICENSE("GPL"); | 427 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/at91/at91rm9200-pcm.h b/sound/soc/at91/at91-pcm.h index 65468f173771..6c3b095725c8 100644 --- a/sound/soc/at91/at91rm9200-pcm.h +++ b/sound/soc/at91/at91-pcm.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * at91rm9200-pcm.h - ALSA PCM interface for the Atmel AT91RM9200 chip | 2 | * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC |
3 | * | 3 | * |
4 | * Author: Frank Mandarino <fmandarino@endrelia.com> | 4 | * Author: Frank Mandarino <fmandarino@endrelia.com> |
5 | * Endrelia Technologies Inc. | 5 | * Endrelia Technologies Inc. |
@@ -16,24 +16,26 @@ | |||
16 | * published by the Free Software Foundation. | 16 | * published by the Free Software Foundation. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <asm/arch/hardware.h> | ||
20 | |||
21 | struct at91_ssc_periph { | ||
22 | void __iomem *base; | ||
23 | u32 pid; | ||
24 | }; | ||
25 | |||
26 | |||
19 | /* | 27 | /* |
20 | * Registers and status bits that are required by the PCM driver. | 28 | * Registers and status bits that are required by the PCM driver. |
21 | */ | 29 | */ |
22 | struct at91rm9200_ssc_regs { | 30 | struct at91_pdc_regs { |
23 | void __iomem *cr; /* SSC control */ | 31 | unsigned int xpr; /* PDC recv/trans pointer */ |
24 | void __iomem *ier; /* SSC interrupt enable */ | 32 | unsigned int xcr; /* PDC recv/trans counter */ |
25 | void __iomem *idr; /* SSC interrupt disable */ | 33 | unsigned int xnpr; /* PDC next recv/trans pointer */ |
34 | unsigned int xncr; /* PDC next recv/trans counter */ | ||
35 | unsigned int ptcr; /* PDC transfer control */ | ||
26 | }; | 36 | }; |
27 | 37 | ||
28 | struct at91rm9200_pdc_regs { | 38 | struct at91_ssc_mask { |
29 | void __iomem *xpr; /* PDC recv/trans pointer */ | ||
30 | void __iomem *xcr; /* PDC recv/trans counter */ | ||
31 | void __iomem *xnpr; /* PDC next recv/trans pointer */ | ||
32 | void __iomem *xncr; /* PDC next recv/trans counter */ | ||
33 | void __iomem *ptcr; /* PDC transfer control */ | ||
34 | }; | ||
35 | |||
36 | struct at91rm9200_ssc_mask { | ||
37 | u32 ssc_enable; /* SSC recv/trans enable */ | 39 | u32 ssc_enable; /* SSC recv/trans enable */ |
38 | u32 ssc_disable; /* SSC recv/trans disable */ | 40 | u32 ssc_disable; /* SSC recv/trans disable */ |
39 | u32 ssc_endx; /* SSC ENDTX or ENDRX */ | 41 | u32 ssc_endx; /* SSC ENDTX or ENDRX */ |
@@ -51,25 +53,19 @@ struct at91rm9200_ssc_mask { | |||
51 | * driver and called by the interface SSC interrupt handler if it is | 53 | * driver and called by the interface SSC interrupt handler if it is |
52 | * non-NULL. | 54 | * non-NULL. |
53 | */ | 55 | */ |
54 | typedef struct { | 56 | struct at91_pcm_dma_params { |
55 | char *name; /* stream identifier */ | 57 | char *name; /* stream identifier */ |
56 | int pdc_xfer_size; /* PDC counter increment in bytes */ | 58 | int pdc_xfer_size; /* PDC counter increment in bytes */ |
57 | struct at91rm9200_ssc_regs *ssc; /* SSC register addresses */ | 59 | void __iomem *ssc_base; /* SSC base address */ |
58 | struct at91rm9200_pdc_regs *pdc; /* PDC receive/transmit registers */ | 60 | struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */ |
59 | struct at91rm9200_ssc_mask *mask;/* SSC & PDC status bits */ | 61 | struct at91_ssc_mask *mask;/* SSC & PDC status bits */ |
60 | snd_pcm_substream_t *substream; | 62 | struct snd_pcm_substream *substream; |
61 | void (*dma_intr_handler)(u32, snd_pcm_substream_t *); | 63 | void (*dma_intr_handler)(u32, struct snd_pcm_substream *); |
62 | } at91rm9200_pcm_dma_params_t; | 64 | }; |
63 | 65 | ||
64 | extern struct snd_soc_cpu_dai at91rm9200_i2s_dai[3]; | 66 | extern struct snd_soc_cpu_dai at91_i2s_dai[3]; |
65 | extern struct snd_soc_platform at91rm9200_soc_platform; | 67 | extern struct snd_soc_platform at91_soc_platform; |
66 | 68 | ||
67 | 69 | ||
68 | /* | ||
69 | * SSC I/O helpers. | ||
70 | * E.g., at91_ssc_write(AT91_SSC(1) + AT91_SSC_CR, AT91_SSC_RXEN); | ||
71 | */ | ||
72 | #define AT91_SSC(x) (((x)==0) ? AT91_VA_BASE_SSC0 :\ | ||
73 | ((x)==1) ? AT91_VA_BASE_SSC1 : ((x)==2) ? AT91_VA_BASE_SSC2 : NULL) | ||
74 | #define at91_ssc_read(a) ((unsigned long) __raw_readl(a)) | 70 | #define at91_ssc_read(a) ((unsigned long) __raw_readl(a)) |
75 | #define at91_ssc_write(a,v) __raw_writel((v),(a)) | 71 | #define at91_ssc_write(a,v) __raw_writel((v),(a)) |
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c index d955cacf2d0d..089cdc9e7265 100644 --- a/sound/soc/at91/eti_b1_wm8731.c +++ b/sound/soc/at91/eti_b1_wm8731.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * eti_b1_wm8731 -- SoC audio for Endrelia ETI_B1. | 2 | * eti_b1_wm8731 -- SoC audio for AT91RM9200-based Endrelia ETI_B1 board. |
3 | * | 3 | * |
4 | * Author: Frank Mandarino <fmandarino@endrelia.com> | 4 | * Author: Frank Mandarino <fmandarino@endrelia.com> |
5 | * Endrelia Technologies Inc. | 5 | * Endrelia Technologies Inc. |
@@ -37,12 +37,12 @@ | |||
37 | #include <sound/soc.h> | 37 | #include <sound/soc.h> |
38 | #include <sound/soc-dapm.h> | 38 | #include <sound/soc-dapm.h> |
39 | 39 | ||
40 | #include <asm/arch/at91rm9200.h> | ||
41 | #include <asm/arch/gpio.h> | ||
42 | #include <asm/arch/hardware.h> | 40 | #include <asm/arch/hardware.h> |
41 | #include <asm/arch/at91_pio.h> | ||
42 | #include <asm/arch/gpio.h> | ||
43 | 43 | ||
44 | #include "../codecs/wm8731.h" | 44 | #include "../codecs/wm8731.h" |
45 | #include "at91rm9200-pcm.h" | 45 | #include "at91-pcm.h" |
46 | 46 | ||
47 | #if 0 | 47 | #if 0 |
48 | #define DBG(x...) printk(KERN_INFO "eti_b1_wm8731:" x) | 48 | #define DBG(x...) printk(KERN_INFO "eti_b1_wm8731:" x) |
@@ -50,10 +50,18 @@ | |||
50 | #define DBG(x...) | 50 | #define DBG(x...) |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | #define AT91_PIO_TF1 (1 << (AT91_PIN_PB6 - PIN_BASE) % 32) | ||
54 | #define AT91_PIO_TK1 (1 << (AT91_PIN_PB7 - PIN_BASE) % 32) | ||
55 | #define AT91_PIO_TD1 (1 << (AT91_PIN_PB8 - PIN_BASE) % 32) | ||
56 | #define AT91_PIO_RD1 (1 << (AT91_PIN_PB9 - PIN_BASE) % 32) | ||
57 | #define AT91_PIO_RK1 (1 << (AT91_PIN_PB10 - PIN_BASE) % 32) | ||
58 | #define AT91_PIO_RF1 (1 << (AT91_PIN_PB11 - PIN_BASE) % 32) | ||
59 | |||
60 | |||
53 | static struct clk *pck1_clk; | 61 | static struct clk *pck1_clk; |
54 | static struct clk *pllb_clk; | 62 | static struct clk *pllb_clk; |
55 | 63 | ||
56 | static int eti_b1_startup(snd_pcm_substream_t *substream) | 64 | static int eti_b1_startup(struct snd_pcm_substream *substream) |
57 | { | 65 | { |
58 | /* Start PCK1 clock. */ | 66 | /* Start PCK1 clock. */ |
59 | clk_enable(pck1_clk); | 67 | clk_enable(pck1_clk); |
@@ -62,7 +70,7 @@ static int eti_b1_startup(snd_pcm_substream_t *substream) | |||
62 | return 0; | 70 | return 0; |
63 | } | 71 | } |
64 | 72 | ||
65 | static void eti_b1_shutdown(snd_pcm_substream_t *substream) | 73 | static void eti_b1_shutdown(struct snd_pcm_substream *substream) |
66 | { | 74 | { |
67 | /* Stop PCK1 clock. */ | 75 | /* Stop PCK1 clock. */ |
68 | clk_disable(pck1_clk); | 76 | clk_disable(pck1_clk); |
@@ -138,7 +146,7 @@ unsigned int eti_b1_config_sysclk(struct snd_soc_pcm_runtime *rtd, | |||
138 | static struct snd_soc_dai_link eti_b1_dai = { | 146 | static struct snd_soc_dai_link eti_b1_dai = { |
139 | .name = "WM8731", | 147 | .name = "WM8731", |
140 | .stream_name = "WM8731", | 148 | .stream_name = "WM8731", |
141 | .cpu_dai = &at91rm9200_i2s_dai[1], | 149 | .cpu_dai = &at91_i2s_dai[1], |
142 | .codec_dai = &wm8731_dai, | 150 | .codec_dai = &wm8731_dai, |
143 | .init = eti_b1_wm8731_init, | 151 | .init = eti_b1_wm8731_init, |
144 | .config_sysclk = eti_b1_config_sysclk, | 152 | .config_sysclk = eti_b1_config_sysclk, |
@@ -157,7 +165,7 @@ static struct wm8731_setup_data eti_b1_wm8731_setup = { | |||
157 | 165 | ||
158 | static struct snd_soc_device eti_b1_snd_devdata = { | 166 | static struct snd_soc_device eti_b1_snd_devdata = { |
159 | .machine = &snd_soc_machine_eti_b1, | 167 | .machine = &snd_soc_machine_eti_b1, |
160 | .platform = &at91rm9200_soc_platform, | 168 | .platform = &at91_soc_platform, |
161 | .codec_dev = &soc_codec_dev_wm8731, | 169 | .codec_dev = &soc_codec_dev_wm8731, |
162 | .codec_data = &eti_b1_wm8731_setup, | 170 | .codec_data = &eti_b1_wm8731_setup, |
163 | }; | 171 | }; |
@@ -168,22 +176,41 @@ static int __init eti_b1_init(void) | |||
168 | { | 176 | { |
169 | int ret; | 177 | int ret; |
170 | u32 ssc_pio_lines; | 178 | u32 ssc_pio_lines; |
179 | struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data; | ||
180 | |||
181 | if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) { | ||
182 | DBG("SSC1 memory region is busy\n"); | ||
183 | return -EBUSY; | ||
184 | } | ||
185 | |||
186 | ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K); | ||
187 | if (!ssc->base) { | ||
188 | DBG("SSC1 memory ioremap failed\n"); | ||
189 | ret = -ENOMEM; | ||
190 | goto fail_release_mem; | ||
191 | } | ||
192 | |||
193 | ssc->pid = AT91RM9200_ID_SSC1; | ||
171 | 194 | ||
172 | eti_b1_snd_device = platform_device_alloc("soc-audio", -1); | 195 | eti_b1_snd_device = platform_device_alloc("soc-audio", -1); |
173 | if (!eti_b1_snd_device) | 196 | if (!eti_b1_snd_device) { |
174 | return -ENOMEM; | 197 | DBG("platform device allocation failed\n"); |
198 | ret = -ENOMEM; | ||
199 | goto fail_io_unmap; | ||
200 | } | ||
175 | 201 | ||
176 | platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata); | 202 | platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata); |
177 | eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev; | 203 | eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev; |
178 | 204 | ||
179 | ret = platform_device_add(eti_b1_snd_device); | 205 | ret = platform_device_add(eti_b1_snd_device); |
180 | if (ret) { | 206 | if (ret) { |
207 | DBG("platform device add failed\n"); | ||
181 | platform_device_put(eti_b1_snd_device); | 208 | platform_device_put(eti_b1_snd_device); |
182 | return ret; | 209 | goto fail_io_unmap; |
183 | } | 210 | } |
184 | 211 | ||
185 | ssc_pio_lines = AT91_PB6_TF1 | AT91_PB7_TK1 | AT91_PB8_TD1 | 212 | ssc_pio_lines = AT91_PIO_TF1 | AT91_PIO_TK1 | AT91_PIO_TD1 |
186 | | AT91_PB9_RD1 /* | AT91_PB10_RK1 | AT91_PB11_RF1 */; | 213 | | AT91_PIO_RD1 /* | AT91_PIO_RK1 | AT91_PIO_RF1 */; |
187 | 214 | ||
188 | /* Reset all PIO registers and assign lines to peripheral A */ | 215 | /* Reset all PIO registers and assign lines to peripheral A */ |
189 | at91_sys_write(AT91_PIOB + PIO_PDR, ssc_pio_lines); | 216 | at91_sys_write(AT91_PIOB + PIO_PDR, ssc_pio_lines); |
@@ -211,14 +238,25 @@ static int __init eti_b1_init(void) | |||
211 | at91_set_B_periph(AT91_PIN_PA24, 0); | 238 | at91_set_B_periph(AT91_PIN_PA24, 0); |
212 | 239 | ||
213 | return ret; | 240 | return ret; |
241 | |||
242 | fail_io_unmap: | ||
243 | iounmap(ssc->base); | ||
244 | fail_release_mem: | ||
245 | release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K); | ||
246 | return ret; | ||
214 | } | 247 | } |
215 | 248 | ||
216 | static void __exit eti_b1_exit(void) | 249 | static void __exit eti_b1_exit(void) |
217 | { | 250 | { |
251 | struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data; | ||
252 | |||
218 | clk_put(pck1_clk); | 253 | clk_put(pck1_clk); |
219 | clk_put(pllb_clk); | 254 | clk_put(pllb_clk); |
220 | 255 | ||
221 | platform_device_unregister(eti_b1_snd_device); | 256 | platform_device_unregister(eti_b1_snd_device); |
257 | |||
258 | iounmap(ssc->base); | ||
259 | release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K); | ||
222 | } | 260 | } |
223 | 261 | ||
224 | module_init(eti_b1_init); | 262 | module_init(eti_b1_init); |