1 /*	$NetBSD: aica_arm.c,v 1.5 2009/03/18 10:22:27 cegger Exp $	*/
2 
3 /*
4  * Copyright (c) 2003 SHIMIZU Ryo <ryo@misakimix.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 typedef	unsigned char	uint8_t;
32 typedef	unsigned short	uint16_t;
33 typedef	unsigned long	uint32_t;
34 
35 #include <arch/dreamcast/dev/g2/aicavar.h>
36 
37 #define	DC_REG_ADDR	0x00800000
38 
39 #define	REG_READ_1(off)		\
40 	(*(volatile uint8_t *)(DC_REG_ADDR + (off)))
41 #define	REG_READ_2(off)		\
42 	(*(volatile uint16_t *)(DC_REG_ADDR + (off)))
43 #define	REG_READ_4(off)		\
44 	(*(volatile uint32_t *)(DC_REG_ADDR + (off)))
45 #define	REG_WRITE_1(off,val)	\
46 	((*(volatile uint8_t *)(DC_REG_ADDR + (off))) = (val))
47 #define	REG_WRITE_2(off,val)	\
48 	((*(volatile uint16_t *)(DC_REG_ADDR + (off))) = (val))
49 #define	REG_WRITE_4(off,val)	\
50 	((*(volatile uint32_t *)((DC_REG_ADDR)+(off))) = (val))
51 
52 #define	CH_READ_1(ch,off)	REG_READ_1(((ch) << 7) + (off))
53 #define	CH_READ_2(ch,off)	REG_READ_2(((ch) << 7) + (off))
54 #define	CH_READ_4(ch,off)	REG_READ_4(((ch) << 7) + (off))
55 #define	CH_WRITE_1(ch,off,val)	REG_WRITE_1(((ch) << 7) + (off), val)
56 #define	CH_WRITE_2(ch,off,val)	REG_WRITE_2(((ch) << 7) + (off), val)
57 #define	CH_WRITE_4(ch,off,val)	REG_WRITE_4(((ch) << 7) + (off), val)
58 
59 void aica_init(void);
60 inline int in_first_half(unsigned int);
61 inline int in_second_half(unsigned int);
62 void bzero_4(void *, unsigned int);
63 void bzero(void *, unsigned int);
64 uint32_t rate2reg(unsigned int);
65 void aica_stop(void);
66 void aica_main(void);
67 
68 void
69 aica_init(void)
70 {
71 	int ch, off;
72 
73 	/* Initialize AICA channels */
74 	REG_WRITE_4(0x2800, 0x0000);	/* Master volume: Min */
75 
76 	for (ch = 0; ch < 64; ch++) {
77 		CH_WRITE_4(ch, 0x00, 0x8000);	/* Key off */
78 		CH_WRITE_4(ch, 0x04, 0x0000);	/* DataAddress (low) */
79 		CH_WRITE_4(ch, 0x08, 0x0000);	/* LoopStartPosition */
80 		CH_WRITE_4(ch, 0x0c, 0x0000);	/* LoopEndPosition */
81 		CH_WRITE_4(ch, 0x10, 0x001f);	/* AR = 0x1f = 0 msec */
82 		CH_WRITE_4(ch, 0x14, 0x001f);	/* RR = 0x1f = 0 msec */
83 		CH_WRITE_4(ch, 0x18, 0x0000);	/* Pitch */
84 		CH_WRITE_4(ch, 0x1c, 0x0000);	/* LFO Control */
85 		CH_WRITE_4(ch, 0x20, 0x0000);	/* DSP Channel to send */
86 		CH_WRITE_4(ch, 0x24, 0x0000);	/* Pan & Volume */
87 		CH_WRITE_4(ch, 0x28, 0x0024);	/* Volume & LowPassFilter */
88 		CH_WRITE_4(ch, 0x2c, 0x0000);	/* LowPassFilter for Attack  */
89 		CH_WRITE_4(ch, 0x30, 0x0000);	/* LowPassFilter for Decay   */
90 		CH_WRITE_4(ch, 0x34, 0x0000);	/* LowPassFilter for Sustain */
91 		CH_WRITE_4(ch, 0x38, 0x0000);	/* LowPassFilter for Keyoff  */
92 		CH_WRITE_4(ch, 0x3c, 0x0000);	/* LowPassFilter for Release */
93 		CH_WRITE_4(ch, 0x40, 0x0000);	/* LowPassFilter transition
94 						   for Attack, Decay */
95 		CH_WRITE_4(ch, 0x44, 0x0000);	/* LowPassFilter transition
96 						   for Decay, Release */
97 
98 		for (off = 0x48; off < 0x80; off+=4) {
99 			CH_WRITE_4(ch, off, 0x0000);	/* other = 0 */
100 		}
101 	}
102 
103 	REG_WRITE_4(0x2800, 0x000f);	/* Master volume: Max */
104 }
105 
106 
107 inline int
108 in_first_half(unsigned int loophalf)
109 {
110 
111 	REG_WRITE_1(0x280d, 0);	/* select channel 0 */
112 	return REG_READ_4(0x2814) < loophalf;
113 }
114 
115 inline int
116 in_second_half(unsigned int loophalf)
117 {
118 
119 	REG_WRITE_1(0x280d, 0);	/* select channel 0 */
120 	return REG_READ_4(0x2814) >= loophalf;
121 }
122 
123 
124 void
125 bzero_4(void *b, unsigned int len)
126 {
127 	uint32_t *p;
128 
129 	p = b;
130 	len = (len + 3) & ~3;
131 	for (; len != 0; len -= 4)
132 		*p++ = 0;
133 }
134 
135 void
136 bzero(void *b,unsigned int len)
137 {
138 	uint8_t *p;
139 
140 	p = b;
141 	for (; len != 0; len--)
142 		*p++ = 0;
143 }
144 
145 
146 uint32_t
147 rate2reg(unsigned int rate)
148 {
149 	uint32_t base, fns;
150 	int oct;
151 
152 	base = 44100 << 7;
153 	for (oct = 7; oct >= -8 && rate < base; oct--)
154 		base >>= 1;
155 
156 	if (rate < base)
157 		return (oct << 11) & 0xf800;
158 
159 	rate -= base;
160 
161 #if 0
162 	/* (base / 2) : round off */
163 	fns = (rate * 1024 + (base / 2)) / base;
164 #else
165 	/* avoid using udivsi3() */
166 	{
167 		uint32_t tmp = (rate * 1024 + (base / 2));
168 		for (fns = 0; tmp >= base; tmp -= base, fns++)
169 			;
170 	}
171 #endif
172 
173 	/* adjustment */
174 	if (fns == 1024) {
175 		oct++;
176 		fns = 0;
177 	} else {
178 		if ((rate > base * fns / 1024) &&
179 		    (fns < 1023) &&
180 		    (rate == base * (fns + 1) / 1024)) {
181 			fns++;
182 		} else if ((rate < base * fns / 1024) &&
183 		           (fns > 0) &&
184 		           (rate == base * (fns - 1)/ 1024)) {
185 			fns--;
186 		}
187 	}
188 
189 	return ((oct << 11) & 0xf800) + fns;
190 }
191 
192 
193 
194 void
195 aica_stop(void)
196 {
197 
198 	CH_WRITE_4(0, 0x00, 0x8000);
199 	CH_WRITE_4(1, 0x00, 0x8000);
200 	bzero_4((void *)AICA_DMABUF_LEFT, AICA_DMABUF_SIZE);
201 	bzero_4((void *)AICA_DMABUF_RIGHT, AICA_DMABUF_SIZE);
202 }
203 
204 void
205 aica_main(void)
206 {
207 	volatile aica_cmd_t *aicacmd = (volatile aica_cmd_t *)AICA_ARM_CMD;
208 	int play_state;
209 	unsigned int loopend = 0,loophalf = 0;
210 	unsigned int blksize = 0, ratepitch;
211 	uint32_t cmd, serial;
212 
213 	aica_init();
214 
215 	REG_WRITE_4(0x28b4, 0x0020);	/* INT Enable to SH4 */
216 
217 	bzero_4((void *)AICA_DMABUF_LEFT, AICA_DMABUF_SIZE);
218 	bzero_4((void *)AICA_DMABUF_RIGHT, AICA_DMABUF_SIZE);
219 
220 	play_state = 0;
221 	serial = aicacmd->serial = 0;
222 
223 	for (;;) {
224 		if (serial != aicacmd->serial) {
225 			serial = aicacmd->serial;
226 			cmd = aicacmd->command;
227 			aicacmd->command = AICA_COMMAND_NOP;
228 		} else {
229 			cmd = AICA_COMMAND_NOP;
230 		}
231 
232 		switch (cmd) {
233 		case AICA_COMMAND_NOP:
234 			/*
235 			 * AICA_COMMAND_NOP - Idle process
236 			 */
237 			switch (play_state) {
238 			case 0: /* not playing */
239 				break;
240 			case 1: /* first half */
241 				if (in_second_half(loophalf)) {
242 					/* Send INT to SH4 */
243 					REG_WRITE_4(0x28b8, 0x0020);
244 					play_state = 2;
245 				}
246 				break;
247 			case 2: /* second half */
248 				if (in_first_half(loophalf)) {
249 					/* Send INT to SH4 */
250 					REG_WRITE_4(0x28b8, 0x0020);
251 					play_state = 1;
252 				}
253 				break;
254 			case 3:
255 				if (in_second_half(loophalf)) {
256 					aica_stop();
257 					play_state = 0;
258 				}
259 				break;
260 			case 4:
261 				if (in_first_half(loophalf)) {
262 					aica_stop();
263 					play_state = 0;
264 				}
265 				break;
266 			}
267 			break;
268 
269 		case AICA_COMMAND_PLAY:
270 			blksize = aicacmd->blocksize;
271 
272 			CH_WRITE_4(0, 0x00, 0x8000);
273 			CH_WRITE_4(1, 0x00, 0x8000);
274 
275 			switch (aicacmd->precision) {
276 			case 16:
277 				loopend = blksize;
278 				break;
279 			case 8:
280 				loopend = blksize * 2;
281 				break;
282 			case 4:
283 				loopend = blksize * 4;
284 				break;
285 			}
286 			loophalf = loopend / 2;
287 
288 			ratepitch = rate2reg(aicacmd->rate);
289 
290 			/* setup left */
291 			CH_WRITE_4(0, 0x08, 0);		/* loop start */
292 			CH_WRITE_4(0, 0x0c, loopend);	/* loop end */
293 			CH_WRITE_4(0, 0x18, ratepitch);	/* SamplingRate */
294 			CH_WRITE_4(0, 0x24, 0x0f1f);	/* volume MAX,
295 							   right PAN */
296 
297 			/* setup right */
298 			CH_WRITE_4(1, 0x08,0);		/* loop start */
299 			CH_WRITE_4(1, 0x0c, loopend);	/* loop end */
300 			CH_WRITE_4(1, 0x18, ratepitch);	/* SamplingRate */
301 			CH_WRITE_4(1, 0x24, 0x0f0f);	/* volume MAX,
302 							   right PAN */
303 
304 			{
305 				uint32_t mode, lparam, rparam;
306 
307 				if (aicacmd->precision == 4)
308 					mode = 3 << 7;	/* 4bit ADPCM */
309 				else if (aicacmd->precision == 8)
310 					mode = 1 << 7;	/* 8bit */
311 				else
312 					mode = 0;	/* 16bit */
313 
314 				switch (aicacmd->channel) {
315 				case 2:
316 					CH_WRITE_4(0, 0x04,
317 					    AICA_DMABUF_LEFT & 0xffff);
318 					CH_WRITE_4(1, 0x04,
319 					    AICA_DMABUF_RIGHT & 0xffff);
320 					lparam = 0xc000 /*PLAY*/ |
321 					    0x0200 /*LOOP*/ | mode |
322 					    (AICA_DMABUF_LEFT >> 16);
323 					rparam = 0xc000 /*PLAY*/ |
324 					    0x0200 /*LOOP*/ | mode |
325 					    (AICA_DMABUF_RIGHT >> 16);
326 					CH_WRITE_4(0, 0x00, lparam);
327 					CH_WRITE_4(1, 0x00, rparam);
328 					break;
329 				case 1:
330 					CH_WRITE_1(0, 0x24, 0);	/* middle
331 								   balance */
332 					CH_WRITE_4(0, 0x04,
333 					    AICA_DMABUF_LEFT & 0xffff);
334 					CH_WRITE_4(0, 0x00, 0xc000 /*PLAY*/ |
335 					    0x0200 /*LOOP*/ | mode |
336 					    (AICA_DMABUF_LEFT >> 16));
337 					break;
338 				}
339 			}
340 			play_state = 1;
341 			break;
342 
343 		case AICA_COMMAND_STOP:
344 			switch (play_state) {
345 			case 1:
346 				bzero_4((void *)(AICA_DMABUF_LEFT + blksize),
347 				    blksize);
348 				bzero_4((void *)(AICA_DMABUF_RIGHT + blksize),
349 				    blksize);
350 				play_state = 3;
351 				break;
352 			case 2:
353 				bzero_4((void *)AICA_DMABUF_LEFT, blksize);
354 				bzero_4((void *)AICA_DMABUF_RIGHT, blksize);
355 				play_state = 4;
356 				break;
357 			default:
358 				aica_stop();
359 				play_state = 0;
360 				break;
361 			}
362 			break;
363 
364 		case AICA_COMMAND_INIT:
365 			aica_stop();
366 			play_state = 0;
367 			break;
368 
369 		case AICA_COMMAND_MVOL:
370 			REG_WRITE_4(0x2800, L256TO16(aicacmd->l_param));
371 			break;
372 
373 		case AICA_COMMAND_VOL:
374 			CH_WRITE_1(0, 0x29, 0xff - (aicacmd->l_param & 0xff));
375 			CH_WRITE_1(1, 0x29, 0xff - (aicacmd->r_param & 0xff));
376 			break;
377 
378 		}
379 	}
380 }
381