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 // Audio Interface Registers
56 #define AI_STREAM_VOL 1
57 #define AI_SAMPLE_COUNT 2
58 #define AI_INT_TIMING 3
62 #define AI_AIINTMSK 0x04
64 #define AI_AIINTVLD 0x10
65 #define AI_SCRESET 0x20
68 #define _SHIFTL(v, s, w) \
69 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
70 #define _SHIFTR(v, s, w) \
71 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
74 static vu32
* const _aiReg
= (u32
*)0xCC006C00;
76 static vu32
* const _aiReg
= (u32
*)0xCD006C00;
78 #error HW model not supported.
81 static vu16
* const _dspReg
= (u16
*)0xCC005000;
83 static u32 __AIInitFlag
= 0;
84 static u32 __AIActive
= 0;
85 static u8
*__CallbackStack
= NULL
;
86 static u8
*__OldStack
= NULL
;
88 static u64 bound_32KHz
,bound_48KHz
,min_wait
,max_wait
,buffer
;
91 static AISCallback __AIS_Callback
;
93 static AIDCallback __AID_Callback
;
95 static void __AICallbackStackSwitch(AIDCallback handler
)
97 __asm__
__volatile__("mflr %r0\n\
102 lis %r5,__OldStack@ha\n\
103 addi %r5,%r5,__OldStack@l\n\
105 lis %r5,__CallbackStack@ha\n\
106 addi %r5,%r5,__CallbackStack@l\n\
111 lis %r5,__OldStack@ha\n\
112 addi %r5,%r5,__OldStack@l\n\
122 static void __AISHandler(u32 nIrq
,void *pCtx
)
125 __AIS_Callback(_aiReg
[AI_SAMPLE_COUNT
]);
126 _aiReg
[AI_CONTROL
] |= AI_AIINT
;
130 static void __AIDHandler(u32 nIrq
,void *pCtx
)
132 _dspReg
[5] = (_dspReg
[5]&~(DSPCR_DSPINT
|DSPCR_ARINT
))|DSPCR_AIINT
;
137 __AICallbackStackSwitch(__AID_Callback
);
145 static void __AISRCINIT()
149 u64 time1
, time2
, tdiff
;
153 _aiReg
[AI_CONTROL
] |= AI_SCRESET
;
154 _aiReg
[AI_CONTROL
] &= ~AI_AISFR
;
155 _aiReg
[AI_CONTROL
] |= AI_PSTAT
;
158 sample_counter
= _aiReg
[AI_SAMPLE_COUNT
];
159 while (sample_counter
== _aiReg
[AI_SAMPLE_COUNT
]) {}
161 sample_counter
= _aiReg
[AI_SAMPLE_COUNT
] & 0x7fffffff;
162 while (sample_counter
== (_aiReg
[AI_SAMPLE_COUNT
] & 0x7fffffff)) {}
167 _aiReg
[AI_CONTROL
] |= AI_AISFR
;
168 _aiReg
[AI_CONTROL
] |= AI_PSTAT
;
171 sample_counter
= _aiReg
[AI_SAMPLE_COUNT
];
172 while (sample_counter
== _aiReg
[AI_SAMPLE_COUNT
]) {}
174 sample_counter
= _aiReg
[AI_SAMPLE_COUNT
] & 0x7fffffff;
175 while (sample_counter
== (_aiReg
[AI_SAMPLE_COUNT
] & 0x7fffffff)) {}
179 tdiff
= time2
- time1
;
181 _aiReg
[AI_CONTROL
] &= ~AI_AISFR
;
182 _aiReg
[AI_CONTROL
] &= ~AI_PSTAT
;
184 if ((tdiff
> (bound_32KHz
- buffer
)) &&
185 (tdiff
< (bound_32KHz
+ buffer
))) {
186 if (tdiff
< (bound_48KHz
- buffer
)) {
196 while (diff_ticks(time2
, gettime()) < wait
) {}
200 static void __AISetStreamSampleRate(u32 rate
)
203 u32 playstate
,volright
,volleft
,dsprate
;
205 currrate
= AUDIO_GetStreamSampleRate();
207 playstate
= AUDIO_GetStreamPlayState();
208 volleft
= AUDIO_GetStreamVolLeft();
209 volright
= AUDIO_GetStreamVolRight();
210 AUDIO_SetStreamVolLeft(0);
211 AUDIO_SetStreamVolRight(0);
212 dsprate
= _aiReg
[AI_CONTROL
]&0x40;
213 _aiReg
[AI_CONTROL
] = _aiReg
[AI_CONTROL
]&~0x40;
215 _CPU_ISR_Disable(level
);
217 _aiReg
[AI_CONTROL
] |= dsprate
;
218 _aiReg
[AI_CONTROL
] = (_aiReg
[AI_CONTROL
]&~0x20)|0x20;
219 _aiReg
[AI_CONTROL
] = (_aiReg
[AI_CONTROL
]&~0x02)|(_SHIFTL(rate
,1,1));
220 _CPU_ISR_Restore(level
);
222 AUDIO_SetStreamPlayState(playstate
);
223 AUDIO_SetStreamVolLeft(volleft
);
224 AUDIO_SetStreamVolRight(volright
);
228 AISCallback
AUDIO_RegisterStreamCallback(AISCallback callback
)
232 AISCallback old
= __AIS_Callback
;
233 _CPU_ISR_Disable(level
);
234 __AIS_Callback
= callback
;
235 _CPU_ISR_Restore(level
);
240 void AUDIO_Init(u8
*stack
)
245 bound_32KHz
= nanosecs_to_ticks(31524);
246 bound_48KHz
= nanosecs_to_ticks(42024);
247 min_wait
= nanosecs_to_ticks(42000);
248 max_wait
= nanosecs_to_ticks(63000);
249 buffer
= nanosecs_to_ticks(3000);
251 _aiReg
[AI_CONTROL
] &= ~(AI_AIINTVLD
|AI_AIINTMSK
|AI_PSTAT
);
255 _aiReg
[AI_CONTROL
] = (_aiReg
[AI_CONTROL
]&~AI_SCRESET
)|AI_SCRESET
;
257 rate
= (_SHIFTR(_aiReg
[AI_CONTROL
],6,1))^1;
258 if(rate
==AI_SAMPLERATE_48KHZ
) {
259 _aiReg
[AI_CONTROL
] &= ~AI_DMAFR
;
260 _CPU_ISR_Disable(level
);
262 _aiReg
[AI_CONTROL
] |= AI_DMAFR
;
263 _CPU_ISR_Restore(level
);
266 __AID_Callback
= NULL
;
268 __OldStack
= NULL
; // davem - use it or lose it
269 // looks like 3.4 isn't picking up the use from the asm below
270 __CallbackStack
= stack
;
272 IRQ_Request(IRQ_DSP_AI
,__AIDHandler
,NULL
);
273 __UnmaskIrq(IRQMASK(IRQ_DSP_AI
));
275 __AIS_Callback
= NULL
;
277 IRQ_Request(IRQ_AI
,__AISHandler
,NULL
);
278 __UnmaskIrq(IRQMASK(IRQ_AI
));
285 void AUDIO_SetStreamVolLeft(u8 vol
)
287 _aiReg
[1] = (_aiReg
[1]&~0x000000ff)|(vol
&0xff);
290 u8
AUDIO_GetStreamVolLeft()
292 return (u8
)(_aiReg
[1]&0xff);
295 void AUDIO_SetStreamVolRight(u8 vol
)
297 _aiReg
[1] = (_aiReg
[1]&~0x0000ff00)|(_SHIFTL(vol
,8,8));
300 u8
AUDIO_GetStreamVolRight()
302 return (u8
)(_SHIFTR(_aiReg
[1],8,8));
305 void AUDIO_SetStreamSampleRate(u32 rate
)
307 _aiReg
[AI_CONTROL
] = (_aiReg
[AI_CONTROL
]&~AI_AISFR
)|(_SHIFTL(rate
,1,1));
310 u32
AUDIO_GetStreamSampleRate()
312 return _SHIFTR(_aiReg
[AI_CONTROL
],1,1);
315 void AUDIO_SetStreamTrigger(u32 cnt
)
320 void AUDIO_ResetStreamSampleCnt()
322 _aiReg
[AI_CONTROL
] = (_aiReg
[AI_CONTROL
]&~AI_SCRESET
)|AI_SCRESET
;
325 void AUDIO_SetStreamPlayState(u32 state
)
327 u32 playstate
,streamrate
;
328 u32 volright
,volleft
,level
;
330 playstate
= AUDIO_GetStreamPlayState();
331 streamrate
= AUDIO_GetStreamSampleRate();
332 if(playstate
!=state
&& state
==AI_STREAM_START
&& streamrate
==AI_SAMPLERATE_32KHZ
) {
333 volright
= AUDIO_GetStreamVolRight();
334 AUDIO_SetStreamVolRight(0);
335 volleft
= AUDIO_GetStreamVolLeft();
336 AUDIO_SetStreamVolLeft(0);
338 _CPU_ISR_Disable(level
);
340 _aiReg
[AI_CONTROL
] = (_aiReg
[AI_CONTROL
]&~AI_SCRESET
)|AI_SCRESET
;
341 _aiReg
[AI_CONTROL
] = (_aiReg
[AI_CONTROL
]&~0x01)|0x01;
342 _CPU_ISR_Restore(level
);
343 AUDIO_SetStreamVolRight(volright
);
344 AUDIO_SetStreamVolLeft(volleft
);
346 _aiReg
[AI_CONTROL
] = (_aiReg
[AI_CONTROL
]&~AI_PSTAT
)|(state
&AI_PSTAT
);
350 u32
AUDIO_GetStreamPlayState()
352 return (_aiReg
[AI_CONTROL
]&AI_PSTAT
);
356 AIDCallback
AUDIO_RegisterDMACallback(AIDCallback callback
)
361 _CPU_ISR_Disable(level
);
362 old
= __AID_Callback
;
363 __AID_Callback
= callback
;
364 _CPU_ISR_Restore(level
);
368 void AUDIO_InitDMA(u32 startaddr
,u32 len
)
372 _CPU_ISR_Disable(level
);
373 _dspReg
[24] = (_dspReg
[24]&~0x1fff)|(_SHIFTR(startaddr
,16,13));
374 _dspReg
[25] = (_dspReg
[25]&~0xffe0)|(startaddr
&0xffff);
375 _dspReg
[27] = (_dspReg
[27]&~0x7fff)|(_SHIFTR(len
,5,15));
376 _CPU_ISR_Restore(level
);
379 u16
AUDIO_GetDMAEnableFlag()
381 return (_SHIFTR(_dspReg
[27],15,1));
384 void AUDIO_StartDMA()
386 _dspReg
[27] = (_dspReg
[27]&~0x8000)|0x8000;
391 _dspReg
[27] = (_dspReg
[27]&~0x8000);
394 u32
AUDIO_GetDMABytesLeft()
396 return (_SHIFTL(_dspReg
[29],5,15));
399 u32
AUDIO_GetDMAStartAddr()
401 return (_SHIFTL((_dspReg
[24]&0x1fff),16,13)|(_dspReg
[25]&0xffe0));
404 u32
AUDIO_GetDMALength()
406 return ((_dspReg
[27]&0x7fff)<<5);
409 void AUDIO_SetDSPSampleRate(u8 rate
)
413 if(AUDIO_GetDSPSampleRate()!=rate
) {
414 _aiReg
[AI_CONTROL
] &= ~AI_DMAFR
;
415 if(rate
==AI_SAMPLERATE_32KHZ
) {
416 _CPU_ISR_Disable(level
);
418 _aiReg
[AI_CONTROL
] |= AI_DMAFR
;
419 _CPU_ISR_Restore(level
);
424 u32
AUDIO_GetDSPSampleRate()
426 return (_SHIFTR(_aiReg
[AI_CONTROL
],6,1))^1; //0^1(1) = 48Khz, 1^1(0) = 32Khz