aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/sh/aica.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 131ec4812288..88dc840152ce 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -106,11 +106,14 @@ static void spu_write_wait(void)
106static void spu_memset(u32 toi, u32 what, int length) 106static void spu_memset(u32 toi, u32 what, int length)
107{ 107{
108 int i; 108 int i;
109 unsigned long flags;
109 snd_assert(length % 4 == 0, return); 110 snd_assert(length % 4 == 0, return);
110 for (i = 0; i < length; i++) { 111 for (i = 0; i < length; i++) {
111 if (!(i % 8)) 112 if (!(i % 8))
112 spu_write_wait(); 113 spu_write_wait();
114 local_irq_save(flags);
113 writel(what, toi + SPU_MEMORY_BASE); 115 writel(what, toi + SPU_MEMORY_BASE);
116 local_irq_restore(flags);
114 toi++; 117 toi++;
115 } 118 }
116} 119}
@@ -118,6 +121,7 @@ static void spu_memset(u32 toi, u32 what, int length)
118/* spu_memload - write to SPU address space */ 121/* spu_memload - write to SPU address space */
119static void spu_memload(u32 toi, void *from, int length) 122static void spu_memload(u32 toi, void *from, int length)
120{ 123{
124 unsigned long flags;
121 u32 *froml = from; 125 u32 *froml = from;
122 u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi); 126 u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
123 int i; 127 int i;
@@ -128,7 +132,9 @@ static void spu_memload(u32 toi, void *from, int length)
128 if (!(i % 8)) 132 if (!(i % 8))
129 spu_write_wait(); 133 spu_write_wait();
130 val = *froml; 134 val = *froml;
135 local_irq_save(flags);
131 writel(val, to); 136 writel(val, to);
137 local_irq_restore(flags);
132 froml++; 138 froml++;
133 to++; 139 to++;
134 } 140 }
@@ -138,28 +144,36 @@ static void spu_memload(u32 toi, void *from, int length)
138static void spu_disable(void) 144static void spu_disable(void)
139{ 145{
140 int i; 146 int i;
147 unsigned long flags;
141 u32 regval; 148 u32 regval;
142 spu_write_wait(); 149 spu_write_wait();
143 regval = readl(ARM_RESET_REGISTER); 150 regval = readl(ARM_RESET_REGISTER);
144 regval |= 1; 151 regval |= 1;
145 spu_write_wait(); 152 spu_write_wait();
153 local_irq_save(flags);
146 writel(regval, ARM_RESET_REGISTER); 154 writel(regval, ARM_RESET_REGISTER);
155 local_irq_restore(flags);
147 for (i = 0; i < 64; i++) { 156 for (i = 0; i < 64; i++) {
148 spu_write_wait(); 157 spu_write_wait();
149 regval = readl(SPU_REGISTER_BASE + (i * 0x80)); 158 regval = readl(SPU_REGISTER_BASE + (i * 0x80));
150 regval = (regval & ~0x4000) | 0x8000; 159 regval = (regval & ~0x4000) | 0x8000;
151 spu_write_wait(); 160 spu_write_wait();
161 local_irq_save(flags);
152 writel(regval, SPU_REGISTER_BASE + (i * 0x80)); 162 writel(regval, SPU_REGISTER_BASE + (i * 0x80));
163 local_irq_restore(flags);
153 } 164 }
154} 165}
155 166
156/* spu_enable - set spu registers to enable sound output */ 167/* spu_enable - set spu registers to enable sound output */
157static void spu_enable(void) 168static void spu_enable(void)
158{ 169{
170 unsigned long flags;
159 u32 regval = readl(ARM_RESET_REGISTER); 171 u32 regval = readl(ARM_RESET_REGISTER);
160 regval &= ~1; 172 regval &= ~1;
161 spu_write_wait(); 173 spu_write_wait();
174 local_irq_save(flags);
162 writel(regval, ARM_RESET_REGISTER); 175 writel(regval, ARM_RESET_REGISTER);
176 local_irq_restore(flags);
163} 177}
164 178
165/* 179/*
@@ -168,25 +182,34 @@ static void spu_enable(void)
168*/ 182*/
169static void spu_reset(void) 183static void spu_reset(void)
170{ 184{
185 unsigned long flags;
171 spu_disable(); 186 spu_disable();
172 spu_memset(0, 0, 0x200000 / 4); 187 spu_memset(0, 0, 0x200000 / 4);
173 /* Put ARM7 in endless loop */ 188 /* Put ARM7 in endless loop */
189 local_irq_save(flags);
174 ctrl_outl(0xea000002, SPU_MEMORY_BASE); 190 ctrl_outl(0xea000002, SPU_MEMORY_BASE);
191 local_irq_restore(flags);
175 spu_enable(); 192 spu_enable();
176} 193}
177 194
178/* aica_chn_start - write to spu to start playback */ 195/* aica_chn_start - write to spu to start playback */
179static void aica_chn_start(void) 196static void aica_chn_start(void)
180{ 197{
198 unsigned long flags;
181 spu_write_wait(); 199 spu_write_wait();
200 local_irq_save(flags);
182 writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT); 201 writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT);
202 local_irq_restore(flags);
183} 203}
184 204
185/* aica_chn_halt - write to spu to halt playback */ 205/* aica_chn_halt - write to spu to halt playback */
186static void aica_chn_halt(void) 206static void aica_chn_halt(void)
187{ 207{
208 unsigned long flags;
188 spu_write_wait(); 209 spu_write_wait();
210 local_irq_save(flags);
189 writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT); 211 writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT);
212 local_irq_restore(flags);
190} 213}
191 214
192/* ALSA code below */ 215/* ALSA code below */
@@ -213,12 +236,13 @@ static int aica_dma_transfer(int channels, int buffer_size,
213 int q, err, period_offset; 236 int q, err, period_offset;
214 struct snd_card_aica *dreamcastcard; 237 struct snd_card_aica *dreamcastcard;
215 struct snd_pcm_runtime *runtime; 238 struct snd_pcm_runtime *runtime;
216 err = 0; 239 unsigned long flags;
217 dreamcastcard = substream->pcm->private_data; 240 dreamcastcard = substream->pcm->private_data;
218 period_offset = dreamcastcard->clicks; 241 period_offset = dreamcastcard->clicks;
219 period_offset %= (AICA_PERIOD_NUMBER / channels); 242 period_offset %= (AICA_PERIOD_NUMBER / channels);
220 runtime = substream->runtime; 243 runtime = substream->runtime;
221 for (q = 0; q < channels; q++) { 244 for (q = 0; q < channels; q++) {
245 local_irq_save(flags);
222 err = dma_xfer(AICA_DMA_CHANNEL, 246 err = dma_xfer(AICA_DMA_CHANNEL,
223 (unsigned long) (runtime->dma_area + 247 (unsigned long) (runtime->dma_area +
224 (AICA_BUFFER_SIZE * q) / 248 (AICA_BUFFER_SIZE * q) /
@@ -228,9 +252,12 @@ static int aica_dma_transfer(int channels, int buffer_size,
228 AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET + 252 AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET +
229 AICA_PERIOD_SIZE * period_offset, 253 AICA_PERIOD_SIZE * period_offset,
230 buffer_size / channels, AICA_DMA_MODE); 254 buffer_size / channels, AICA_DMA_MODE);
231 if (unlikely(err < 0)) 255 if (unlikely(err < 0)) {
256 local_irq_restore(flags);
232 break; 257 break;
258 }
233 dma_wait_for_completion(AICA_DMA_CHANNEL); 259 dma_wait_for_completion(AICA_DMA_CHANNEL);
260 local_irq_restore(flags);
234 } 261 }
235 return err; 262 return err;
236} 263}