1 /*-------------------------------------------------------------
3 audio.c -- Audio subsystem
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
29 -------------------------------------------------------------*/
34 #include "processor.h"
37 #include "lwp_watchdog.h"
39 #define STACKSIZE 16384
42 #define DSPCR_DSPRESET 0x0800 // Reset DSP
43 #define DSPCR_DSPDMA 0x0200 // ARAM dma in progress, if set
44 #define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
45 #define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
46 #define DSPCR_ARINTMSK 0x0040
47 #define DSPCR_ARINT 0x0020
48 #define DSPCR_AIINTMSK 0x0010
49 #define DSPCR_AIINT 0x0008
50 #define DSPCR_HALT 0x0004 // halt DSP
51 #define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
52 #define DSPCR_RES 0x0001 // reset DSP
54 #define _SHIFTL(v, s, w) \
55 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
56 #define _SHIFTR(v, s, w) \
57 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
60 static vu32
* const _aiReg
= (u32
*)0xCC006C00;
62 static vu32
* const _aiReg
= (u32
*)0xCD006C00;
64 #error HW model not supported.
67 static vu16
* const _dspReg
= (u16
*)0xCC005000;
69 static u32 __AIInitFlag
= 0;
70 static u8
*__CallbackStack
= NULL
;
71 static u8
*__OldStack
= NULL
;
73 static u64 bound_32KHz
,bound_48KHz
,min_wait
,max_wait
,buffer
;
75 static AIDCallback __AID_Callback
;
76 static AISCallback __AIS_Callback
;
78 static void __AICallbackStackSwitch(AIDCallback handler
)
80 __asm__
__volatile__("mflr %r0\n\
85 lis %r5,__OldStack@ha\n\
86 addi %r5,%r5,__OldStack@l\n\
88 lis %r5,__CallbackStack@ha\n\
89 addi %r5,%r5,__CallbackStack@l\n\
94 lis %r5,__OldStack@ha\n\
95 addi %r5,%r5,__OldStack@l\n\
104 static void __AISHandler(u32 nIrq
,void *pCtx
)
107 __AIS_Callback(_aiReg
[2]);
111 static void __AIDHandler(u32 nIrq
,void *pCtx
)
115 __AICallbackStackSwitch(__AID_Callback
);
119 _dspReg
[5] = (_dspReg
[5]&~(DSPCR_DSPINT
|DSPCR_ARINT
))|DSPCR_AIINT
;
122 static void __AISRCINIT()
126 static void __AISetStreamSampleRate(u32 rate
)
129 u32 playstate
,volright
,volleft
,dsprate
;
131 currrate
= AUDIO_GetStreamSampleRate();
133 playstate
= AUDIO_GetStreamPlayState();
134 volleft
= AUDIO_GetStreamVolLeft();
135 volright
= AUDIO_GetStreamVolRight();
136 AUDIO_SetStreamVolLeft(0);
137 AUDIO_SetStreamVolRight(0);
138 dsprate
= _aiReg
[0]&0x40;
139 _aiReg
[0] = _aiReg
[0]&~0x40;
141 _CPU_ISR_Disable(level
);
143 _aiReg
[0] |= dsprate
;
144 _aiReg
[0] = (_aiReg
[0]&~0x20)|0x20;
145 _aiReg
[0] = (_aiReg
[0]&~0x02)|(_SHIFTL(rate
,1,1));
146 _CPU_ISR_Restore(level
);
148 AUDIO_SetStreamPlayState(playstate
);
149 AUDIO_SetStreamVolLeft(volleft
);
150 AUDIO_SetStreamVolRight(volright
);
154 AISCallback
AUDIO_RegisterStreamCallback(AISCallback callback
)
158 AISCallback old
= __AIS_Callback
;
159 _CPU_ISR_Disable(level
);
160 __AIS_Callback
= callback
;
161 _CPU_ISR_Restore(level
);
165 void AUDIO_Init(u8
*stack
)
167 u32 busfreq
= TB_BUS_CLOCK
;
170 bound_32KHz
= (u64
)((((busfreq
>>2)/125000)*31524)/8000)<<32;
171 bound_48KHz
= (u64
)((((busfreq
>>2)/125000)*42024)/8000)<<32;
172 min_wait
= (u64
)((((busfreq
>>2)/125000)*42000)/8000)<<32;
173 max_wait
= (u64
)((((busfreq
>>2)/125000)*63000)/8000)<<32;
174 buffer
= (u64
)((((busfreq
>>2)/125000)*3000)/8000)<<32;
176 _aiReg
[0] = (_aiReg
[0]&~0x20)|0x20;
177 _aiReg
[1] = _aiReg
[1]&~0x000000ff;
178 _aiReg
[1] = _aiReg
[1]&~0x0000ff00;
181 __AISetStreamSampleRate(AI_SAMPLERATE_48KHZ
);
182 AUDIO_SetDSPSampleRate(AI_SAMPLERATE_32KHZ
);
184 __AIS_Callback
= NULL
;
185 __AID_Callback
= NULL
;
187 __OldStack
= NULL
; // davem - use it or lose it
188 // looks like 3.4 isn't picking up the use from the asm below
189 __CallbackStack
= stack
;
191 IRQ_Request(IRQ_AI
,__AISHandler
,NULL
);
192 __UnmaskIrq(IRQMASK(IRQ_AI
));
194 IRQ_Request(IRQ_DSP_AI
,__AIDHandler
,NULL
);
195 __UnmaskIrq(IRQMASK(IRQ_DSP_AI
));
201 void AUDIO_SetStreamVolLeft(u8 vol
)
203 _aiReg
[1] = (_aiReg
[1]&~0x000000ff)|(vol
&0xff);
206 u8
AUDIO_GetStreamVolLeft()
208 return (u8
)(_aiReg
[1]&0xff);
211 void AUDIO_SetStreamVolRight(u8 vol
)
213 _aiReg
[1] = (_aiReg
[1]&~0x0000ff00)|(_SHIFTL(vol
,8,8));
216 u8
AUDIO_GetStreamVolRight()
218 return (u8
)(_SHIFTR(_aiReg
[1],8,8));
221 void AUDIO_SetStreamSampleRate(u32 rate
)
223 _aiReg
[0] = (_aiReg
[0]&~0x0002)|(_SHIFTL(rate
,1,1));
226 u32
AUDIO_GetStreamSampleRate()
228 return _SHIFTR(_aiReg
[0],1,1);
231 AIDCallback
AUDIO_RegisterDMACallback(AIDCallback callback
)
236 _CPU_ISR_Disable(level
);
237 old
= __AID_Callback
;
238 __AID_Callback
= callback
;
239 _CPU_ISR_Restore(level
);
243 void AUDIO_InitDMA(u32 startaddr
,u32 len
)
247 _CPU_ISR_Disable(level
);
248 _dspReg
[24] = (_dspReg
[24]&~0x03ff)|(_SHIFTR(startaddr
,16,10));
249 _dspReg
[25] = (_dspReg
[25]&~0xffe0)|(startaddr
&0xffff);
250 _dspReg
[27] = (_dspReg
[27]&~0x7fff)|(_SHIFTR(len
,5,15));
251 _CPU_ISR_Restore(level
);
254 u16
AUDIO_GetDMAEnableFlag()
256 return (_SHIFTR(_dspReg
[27],15,1));
259 void AUDIO_StartDMA()
261 _dspReg
[27] = (_dspReg
[27]&~0x8000)|0x8000;
266 _dspReg
[27] = (_dspReg
[27]&~0x8000);
269 u32
AUDIO_GetDMABytesLeft()
271 return (_SHIFTL(_dspReg
[29],5,15));
274 u32
AUDIO_GetDMAStartAddr()
276 return (_SHIFTL((_dspReg
[24]&0x3ff),16,10)|(_dspReg
[25]&0xffe0));
279 u32
AUDIO_GetDMALength()
281 return ((_dspReg
[26]&0x7fff)<<5);
284 void AUDIO_SetStreamTrigger(u32 cnt
)
289 void AUDIO_ResetStreamSampleCnt()
291 _aiReg
[0] = (_aiReg
[0]&~0x20)|0x20;
294 void AUDIO_SetDSPSampleRate(u8 rate
)
297 u32 playstate
,volright
,volleft
;
299 if(AUDIO_GetDSPSampleRate()!=rate
) {
300 _aiReg
[0] = (_aiReg
[0]&~0x40);
301 if(rate
==AI_SAMPLERATE_32KHZ
) {
302 volright
= AUDIO_GetStreamVolRight();
303 AUDIO_SetStreamVolRight(0);
304 volleft
= AUDIO_GetStreamVolLeft();
305 AUDIO_SetStreamVolLeft(0);
306 playstate
= _aiReg
[0]&0x01;
307 currate
= AUDIO_GetStreamSampleRate();
309 _CPU_ISR_Disable(level
);
311 _aiReg
[0] = (_aiReg
[0]&~0x20)|0x20;
312 _aiReg
[0] = (_aiReg
[0]&~0x02)|(_SHIFTL(currate
,1,1));
313 _aiReg
[0] = (_aiReg
[0]&~0x01)|(playstate
&0x01);
315 _CPU_ISR_Restore(level
);
316 AUDIO_SetStreamVolRight(volright
);
317 AUDIO_SetStreamVolLeft(volleft
);
322 u32
AUDIO_GetDSPSampleRate()
324 return (_SHIFTR(_aiReg
[0],6,1))^1; //0^1(1) = 48Khz, 1^1(0) = 32Khz
327 void AUDIO_SetStreamPlayState(u32 state
)
329 u32 playstate
,streamrate
;
330 u32 volright
,volleft
,level
;
332 playstate
= AUDIO_GetStreamPlayState();
333 streamrate
= AUDIO_GetStreamSampleRate();
334 if(playstate
!=state
&& state
==AI_STREAM_START
&& streamrate
==AI_SAMPLERATE_32KHZ
) {
335 volright
= AUDIO_GetStreamVolRight();
336 AUDIO_SetStreamVolRight(0);
337 volleft
= AUDIO_GetStreamVolLeft();
338 AUDIO_SetStreamVolLeft(0);
340 _CPU_ISR_Disable(level
);
342 _aiReg
[0] = (_aiReg
[0]&~0x20)|0x20;
343 _aiReg
[0] = (_aiReg
[0]&~0x01)|0x01;
344 _CPU_ISR_Restore(level
);
345 AUDIO_SetStreamVolRight(volright
);
346 AUDIO_SetStreamVolLeft(volleft
);
348 _aiReg
[0] = (_aiReg
[0]&~0x01)|(state
&0x01);
352 u32
AUDIO_GetStreamPlayState()
354 return (_aiReg
[0]&0x01);