aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/at91/Makefile4
-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.c64
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
2snd-soc-at91-objs := at91rm9200-pcm.o 2snd-soc-at91-objs := at91-pcm.o
3snd-soc-at91-i2s-objs := at91rm9200-i2s.o 3snd-soc-at91-i2s-objs := at91-i2s.o
4 4
5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o 5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
6obj-$(CONFIG_SND_AT91_SOC_I2S) += snd-soc-at91-i2s.o 6obj-$(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 ) */
51static struct snd_soc_dai_mode at91rm9200_i2s[] = { 58static 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 */
106static struct at91rm9200_ssc_regs ssc_reg[3] = { 113static 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
124static 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
148static struct at91rm9200_pdc_regs pdc_rx_reg[3] = { 120static 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 */
175static struct at91rm9200_ssc_mask ssc_tx_mask = { 130static 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
184static struct at91rm9200_ssc_mask ssc_rx_mask = { 139static 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 */
200static DECLARE_MUTEX(ssc0_mutex);
201static DECLARE_MUTEX(ssc1_mutex);
202static DECLARE_MUTEX(ssc2_mutex);
203 148
204/* 149/*
205 * DMA parameters. 150 * DMA parameters.
206 */ 151 */
207static at91rm9200_pcm_dma_params_t ssc_dma_params[3][2] = { 152static 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
247struct 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 */
195static DECLARE_MUTEX(ssc0_mutex);
196#if NUM_SSC_DEVICES == 3
197static DECLARE_MUTEX(ssc1_mutex);
198static DECLARE_MUTEX(ssc2_mutex);
199#endif
200
201
202struct 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
257static struct at91rm9200_ssc_info { 212
213static 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
301static irqreturn_t at91rm9200_i2s_interrupt(int irq, void *dev_id) 252static 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
330static int at91rm9200_i2s_startup(struct snd_pcm_substream *substream) 281static 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
351static void at91rm9200_i2s_shutdown(struct snd_pcm_substream *substream) 302static 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
391static int at91rm9200_i2s_suspend(struct platform_device *pdev, 344static 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
419static int at91rm9200_i2s_resume(struct platform_device *pdev, 372static 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
450static unsigned int at91rm9200_i2s_config_sysclk( 403static 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
460static int at91rm9200_i2s_hw_params(struct snd_pcm_substream *substream, 413static 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
630static int at91rm9200_i2s_prepare(struct snd_pcm_substream *substream) 582static 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
644struct snd_soc_cpu_dai at91rm9200_i2s_dai[] = { 597struct 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
710EXPORT_SYMBOL_GPL(at91rm9200_i2s_dai); 668EXPORT_SYMBOL_GPL(at91_i2s_dai);
711 669
712/* Module information */ 670/* Module information */
713MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com"); 671MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
714MODULE_DESCRIPTION("AT91RM9200 I2S ASoC Interface"); 672MODULE_DESCRIPTION("AT91 I2S ASoC Interface");
715MODULE_LICENSE("GPL"); 673MODULE_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
44static const snd_pcm_hardware_t at91rm9200_pcm_hardware = { 43static 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
57struct at91rm9200_runtime_data { 56struct 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
69static void at91rm9200_pcm_dma_irq(u32 ssc_sr, 68static 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
116static int at91rm9200_pcm_hw_params(struct snd_pcm_substream *substream, 115static 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
141static int at91rm9200_pcm_hw_free(struct snd_pcm_substream *substream) 140static 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
154static int at91rm9200_pcm_prepare(struct snd_pcm_substream *substream) 153static 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
166static int at91rm9200_pcm_trigger(struct snd_pcm_substream *substream, 165static 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
220static snd_pcm_uframes_t at91rm9200_pcm_pointer( 219static 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
237static int at91rm9200_pcm_open(struct snd_pcm_substream *substream) 236static 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
261static int at91rm9200_pcm_close(struct snd_pcm_substream *substream) 260static 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
269static int at91rm9200_pcm_mmap(struct snd_pcm_substream *substream, 268static 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
280struct snd_pcm_ops at91rm9200_pcm_ops = { 279struct 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
292static int at91rm9200_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, 291static 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
317static u64 at91rm9200_pcm_dmamask = 0xffffffff; 316static u64 at91_pcm_dmamask = 0xffffffff;
318 317
319static int at91rm9200_pcm_new(struct snd_card *card, 318static 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
346static void at91rm9200_pcm_free_dma_buffers(struct snd_pcm *pcm) 345static 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
367static int at91rm9200_pcm_suspend(struct platform_device *pdev, 366static 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
392static int at91rm9200_pcm_resume(struct platform_device *pdev, 391static 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
415struct snd_soc_platform at91rm9200_soc_platform = { 414struct 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
424EXPORT_SYMBOL_GPL(at91rm9200_soc_platform); 423EXPORT_SYMBOL_GPL(at91_soc_platform);
425 424
426MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>"); 425MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
427MODULE_DESCRIPTION("Atmel AT91RM9200 PCM module"); 426MODULE_DESCRIPTION("Atmel AT91 PCM module");
428MODULE_LICENSE("GPL"); 427MODULE_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
21struct 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 */
22struct at91rm9200_ssc_regs { 30struct 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
28struct at91rm9200_pdc_regs { 38struct 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
36struct 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 */
54typedef struct { 56struct 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
64extern struct snd_soc_cpu_dai at91rm9200_i2s_dai[3]; 66extern struct snd_soc_cpu_dai at91_i2s_dai[3];
65extern struct snd_soc_platform at91rm9200_soc_platform; 67extern 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
53static struct clk *pck1_clk; 61static struct clk *pck1_clk;
54static struct clk *pllb_clk; 62static struct clk *pllb_clk;
55 63
56static int eti_b1_startup(snd_pcm_substream_t *substream) 64static 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
65static void eti_b1_shutdown(snd_pcm_substream_t *substream) 73static 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,
138static struct snd_soc_dai_link eti_b1_dai = { 146static 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
158static struct snd_soc_device eti_b1_snd_devdata = { 166static 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
242fail_io_unmap:
243 iounmap(ssc->base);
244fail_release_mem:
245 release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
246 return ret;
214} 247}
215 248
216static void __exit eti_b1_exit(void) 249static 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
224module_init(eti_b1_init); 262module_init(eti_b1_init);