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