1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - libraries - snd
3 File: sndex.c
4
5 Copyright 2008-2009 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2011-11-01#$
14 $Rev: 11432 $
15 $Author: yada $
16 *---------------------------------------------------------------------------*/
17
18 #include <twl/os.h>
19 #include <twl/snd/ARM9/sndex.h>
20 #include <nitro/pxi.h>
21 #include <twl/os/common/codecmode.h>
22
23
24 /*---------------------------------------------------------------------------*
25 Macro definitions
26 *---------------------------------------------------------------------------*/
27 #ifdef SDK_DEBUG
28 #define SNDEXi_Warning OS_TWarning
29 #else
30 #define SNDEXi_Warning(...) ((void)0)
31 #endif
32
33 /*---------------------------------------------------------------------------*
34 Structure definitions
35 *---------------------------------------------------------------------------*/
36
37 /* Work structure for asynchronous processes */
38 typedef struct SNDEXWork
39 {
40 SNDEXCallback callback;
41 void* cbArg;
42 void* dest;
43 u8 command;
44 u8 padding[3];
45
46 } SNDEXWork;
47
48 /* Internal status */
49 typedef enum SNDEXState
50 {
51 SNDEX_STATE_BEFORE_INIT = 0,
52 SNDEX_STATE_INITIALIZING = 1,
53 SNDEX_STATE_INITIALIZED = 2,
54 SNDEX_STATE_LOCKED = 3,
55 SNDEX_STATE_PLAY_SHUTTER = 4, // Shutter sound is playing (exclude all SNDEX functions other than PreProcessForShutterSound and PostProcessForShutterSound)
56 SNDEX_STATE_POST_PROC_SHUTTER = 5, // Currently postprocessing the shutter sound playback (exclude all SNDEX functions)
57 SNDEX_STATE_MAX
58
59 } SNDEXState;
60
61 /* Set audio output device */
62 typedef enum SNDEXDevice
63 {
64 SNDEX_DEVICE_AUTO = 0,
65 SNDEX_DEVICE_SPEAKER = 1,
66 SNDEX_DEVICE_HEADPHONE = 2,
67 SNDEX_DEVICE_BOTH = 3,
68 SNDEX_DEVICE_MAX
69
70 } SNDEXDevice;
71
72 /*---------------------------------------------------------------------------*
73 Variable Definitions
74 *---------------------------------------------------------------------------*/
75 static volatile SNDEXState sndexState = SNDEX_STATE_BEFORE_INIT;
76 static SNDEXWork sndexWork;
77 static SNDEXVolumeSwitchCallbackInfo SNDEXi_VolumeSwitchCallbackInfo = {NULL, NULL, NULL, 0};
78
79 PMSleepCallbackInfo sleepCallbackInfo;
80 PMExitCallbackInfo exitCallbackInfo;
81 static volatile BOOL isIirFilterSetting = FALSE; // TRUE if already executing SetIirFilterAsync
82 static volatile BOOL isLockSpi = FALSE; // Whether SPI exclusion control is currently being applied inside SNDEX_SetIirFilter[Async]
83
84 static volatile BOOL isPlayShutter = FALSE; // TRUE if currently processing shutter sound playback
85 static volatile BOOL isStoreVolume = FALSE; // Whether a volume has been saved by SNDEXi_SetIgnoreHWVolume
86 static u8 storeVolume = 0; // Value of the volume before it is temporarily changed by SNDEXi_SetIgnoreHWVolume
87
88 /*---------------------------------------------------------------------------*
89 Function definitions
90 *---------------------------------------------------------------------------*/
91 static void CommonCallback (PXIFifoTag tag, u32 data, BOOL err);
92 static void SyncCallback (SNDEXResult result, void* arg);
93 static BOOL SendCommand (u8 command, u8 param);
94 static BOOL SendCommandEx (u8 command, u16 param);
95 static SNDEXResult CheckState (void);
96 static void ReplyCallback (SNDEXResult result);
97 static void SetSndexWork (SNDEXCallback cb, void* cbarg, void* dst, u8 command);
98
99 static void SndexSleepAndExitCallback (void *arg);
100
101 static void WaitIirFilterSetting (void);
102 static void WaitResetSoundCallback (SNDEXResult result, void* arg);
103 static void ResetTempVolume (void);
104
105 SNDEXResult SNDEXi_GetDeviceAsync (SNDEXDevice* device, SNDEXCallback callback, void* arg);
106 SNDEXResult SNDEXi_GetDevice (SNDEXDevice* device);
107 SNDEXResult SNDEXi_SetDeviceAsync (SNDEXDevice device, SNDEXCallback callback, void* arg);
108 SNDEXResult SNDEXi_SetDevice (SNDEXDevice device);
109
110 /*---------------------------------------------------------------------------*
111 Name: SNDEXi_Init
112
113 Description: Initializes the extended sound features library.
114
115 Arguments: None.
116
117 Returns: None.
118 *---------------------------------------------------------------------------*/
119 void
SNDEXi_Init(void)120 SNDEXi_Init (void)
121 {
122 OSIntrMode e = OS_DisableInterrupts();
123
124 /* Confirm that initialized */
125 if (sndexState != SNDEX_STATE_BEFORE_INIT)
126 {
127 (void)OS_RestoreInterrupts(e);
128 SNDEXi_Warning("%s: Already initialized.\n", __FUNCTION__);
129 return;
130 }
131 sndexState = SNDEX_STATE_INITIALIZING;
132 (void)OS_RestoreInterrupts(e);
133
134 /* Variable initialization */
135 SetSndexWork(NULL, NULL, NULL, 0);
136
137 /* Stand by until the ARM7's SNDEX library is started */
138 PXI_Init();
139 while (!PXI_IsCallbackReady(PXI_FIFO_TAG_SNDEX, PXI_PROC_ARM7))
140 {
141 SVC_WaitByLoop(10);
142 }
143 /* Set the PXI callback function */
144 PXI_SetFifoRecvCallback(PXI_FIFO_TAG_SNDEX, CommonCallback);
145
146 /* Set the postprocessing callback function for when executing a hardware reset or shutdown*/
147 PM_SetExitCallbackInfo(&exitCallbackInfo, SndexSleepAndExitCallback, NULL);
148 PMi_InsertPostExitCallbackEx(&exitCallbackInfo, PM_CALLBACK_PRIORITY_SNDEX);
149
150 /* Register the pre-sleep callback */
151 PM_SetSleepCallbackInfo(&sleepCallbackInfo, SndexSleepAndExitCallback, NULL);
152 PMi_InsertPreSleepCallbackEx(&sleepCallbackInfo, PM_CALLBACK_PRIORITY_SNDEX);
153
154 /* Initialization complete */
155 sndexState = SNDEX_STATE_INITIALIZED;
156 }
157
158 /*---------------------------------------------------------------------------*
159 Name: SNDEXi_GetMuteAsync
160
161 Description: Asynchronously gets the mute status of the audio output.
162 The buffer should not be used for other purposes until the asynchronous process completes, as results are written to the results buffer asynchronously from the function call.
163
164 Arguments: mute: Buffer used to get the mute status
165 callback: Callback function that notifies of the results when the asynchronous processing is completed.
166 arg: Parameter passed to the callback function
167
168 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
169 *---------------------------------------------------------------------------
170
171
172
173 */
174 SNDEXResult
SNDEXi_GetMuteAsync(SNDEXMute * mute,SNDEXCallback callback,void * arg)175 SNDEXi_GetMuteAsync (SNDEXMute* mute, SNDEXCallback callback, void* arg)
176 {
177 /* No parameter restrictions */
178
179 /* Confirm status */
180 {
181 SNDEXResult result = CheckState();
182 if (result != SNDEX_RESULT_SUCCESS)
183 {
184 return result;
185 }
186 }
187
188 /* Register asynchronous process */
189 SetSndexWork(callback, arg, (void*)mute, SNDEX_PXI_COMMAND_GET_SMIX_MUTE);
190
191 /* Issue command to ARM7 */
192 if (FALSE == SendCommand(sndexWork.command, 0))
193 {
194 return SNDEX_RESULT_PXI_SEND_ERROR;
195 }
196 return SNDEX_RESULT_SUCCESS;
197 }
198
199 /*---------------------------------------------------------------------------*
200 Name: SNDEXi_GetMute
201
202 Description: Gets the mute status of the audio output.
203 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
204
205 Arguments: mute: Buffer used to get the mute status
206
207 Returns: SNDEXResult: Returns processing results.
208 *---------------------------------------------------------------------------*/
209 SNDEXResult
SNDEXi_GetMute(SNDEXMute * mute)210 SNDEXi_GetMute (SNDEXMute* mute)
211 {
212 SNDEXResult result;
213 OSMessageQueue msgQ;
214 OSMessage msg[1];
215
216 /* Calling this from an exception handler is prohibited */
217 if (OS_GetCurrentThread() == NULL)
218 {
219 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
220 return SNDEX_RESULT_ILLEGAL_STATE;
221 }
222
223 /* Initialize the message queue used for synchronization */
224 OS_InitMessageQueue(&msgQ, msg, 1);
225
226 /* Execute the asynchronous function and idle the callback */
227 result = SNDEXi_GetMuteAsync(mute, SyncCallback, (void*)(&msgQ));
228 if (result == SNDEX_RESULT_SUCCESS)
229 {
230 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
231 }
232 return result;
233 }
234
235 /*---------------------------------------------------------------------------*
236 Name: SNDEXi_GetI2SFrequencyAsync
237
238 Description: Asynchronously gets the I2S frequency information.
239 The buffer should not be used for other purposes until the asynchronous process completes, as results are written to the results buffer asynchronously from the function call.
240
241 Arguments: freq: Buffer used to get the frequency information
242 callback: Callback function that notifies of the results when the asynchronous processing is completed.
243 arg: Parameter passed to the callback function
244
245 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
246 *---------------------------------------------------------------------------
247
248
249
250 */
251 SNDEXResult
SNDEXi_GetI2SFrequencyAsync(SNDEXFrequency * freq,SNDEXCallback callback,void * arg)252 SNDEXi_GetI2SFrequencyAsync (SNDEXFrequency* freq, SNDEXCallback callback, void* arg)
253 {
254 /* No parameter restrictions */
255
256 /* Confirm status */
257 {
258 SNDEXResult result = CheckState();
259 if (result != SNDEX_RESULT_SUCCESS)
260 {
261 return result;
262 }
263 }
264
265 /* Register asynchronous process */
266 SetSndexWork(callback, arg, (void*)freq, SNDEX_PXI_COMMAND_GET_SMIX_FREQ);
267
268 /* Issue command to ARM7 */
269 if (FALSE == SendCommand(sndexWork.command, 0))
270 {
271 return SNDEX_RESULT_PXI_SEND_ERROR;
272 }
273 return SNDEX_RESULT_SUCCESS;
274 }
275
276 /*---------------------------------------------------------------------------*
277 Name: SNDEXi_GetI2SFrequency
278
279 Description: Gets I2S frequency information.
280 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
281
282 Arguments: freq: Buffer used to get the frequency information
283
284 Returns: SNDEXResult: Returns processing results.
285 *---------------------------------------------------------------------------*/
286 SNDEXResult
SNDEXi_GetI2SFrequency(SNDEXFrequency * freq)287 SNDEXi_GetI2SFrequency(SNDEXFrequency* freq)
288 {
289 SNDEXResult result;
290 OSMessageQueue msgQ;
291 OSMessage msg[1];
292
293 /* Calling this from an exception handler is prohibited */
294 if (OS_GetCurrentThread() == NULL)
295 {
296 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
297 return SNDEX_RESULT_ILLEGAL_STATE;
298 }
299
300 /* Initialize the message queue used for synchronization */
301 OS_InitMessageQueue(&msgQ, msg, 1);
302
303 /* Execute the asynchronous function and idle the callback */
304 result = SNDEXi_GetI2SFrequencyAsync(freq, SyncCallback, (void*)(&msgQ));
305 if (result == SNDEX_RESULT_SUCCESS)
306 {
307 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
308 }
309 return result;
310 }
311
312 /*---------------------------------------------------------------------------*
313 Name: SNDEXi_GetDSPMixRateAsync
314
315 Description: Gets the audio output mix rate information for the CPU and DSP.
316 Minimum mix rate: 0 (DSP 100%), maximum: 8 (CPU 100%).
317 The buffer should not be used for other purposes until the asynchronous process completes, as results are written to the results buffer asynchronously from the function call.
318
319 Arguments: rate: Buffer used to get the mix rate information
320 callback: Callback function that notifies of the results when the asynchronous processing is completed.
321 arg: Parameter passed to the callback function
322
323 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
324 *---------------------------------------------------------------------------
325
326
327
328 */
329 SNDEXResult
SNDEXi_GetDSPMixRateAsync(u8 * rate,SNDEXCallback callback,void * arg)330 SNDEXi_GetDSPMixRateAsync (u8* rate, SNDEXCallback callback, void* arg)
331 {
332 /* No parameter restrictions */
333
334 /* Confirm status */
335 {
336 SNDEXResult result = CheckState();
337 if (result != SNDEX_RESULT_SUCCESS)
338 {
339 return result;
340 }
341 }
342
343 /* Register asynchronous process */
344 SetSndexWork(callback, arg, (void*)rate, SNDEX_PXI_COMMAND_GET_SMIX_DSP);
345
346 /* Issue command to ARM7 */
347 if (FALSE == SendCommand(sndexWork.command, 0))
348 {
349 return SNDEX_RESULT_PXI_SEND_ERROR;
350 }
351 return SNDEX_RESULT_SUCCESS;
352 }
353
354 /*---------------------------------------------------------------------------*
355 Name: SNDEXi_GetDSPMixRate
356
357 Description: Gets the audio output mix rate information for the CPU and DSP.
358 Minimum mix rate: 0 (DSP 100%), maximum: 8 (CPU 100%).
359 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
360
361 Arguments: rate: Buffer used to get the mix rate information
362
363 Returns: SNDEXResult: Returns processing results.
364 *---------------------------------------------------------------------------*/
365 SNDEXResult
SNDEXi_GetDSPMixRate(u8 * rate)366 SNDEXi_GetDSPMixRate (u8* rate)
367 {
368 SNDEXResult result;
369 OSMessageQueue msgQ;
370 OSMessage msg[1];
371
372 /* Calling this from an exception handler is prohibited */
373 if (OS_GetCurrentThread() == NULL)
374 {
375 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
376 return SNDEX_RESULT_ILLEGAL_STATE;
377 }
378
379 /* Initialize the message queue used for synchronization */
380 OS_InitMessageQueue(&msgQ, msg, 1);
381
382 /* Execute the asynchronous function and idle the callback */
383 result = SNDEXi_GetDSPMixRateAsync(rate, SyncCallback, (void*)(&msgQ));
384 if (result == SNDEX_RESULT_SUCCESS)
385 {
386 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
387 }
388 return result;
389 }
390
391 /*---------------------------------------------------------------------------*
392 Name: SNDEXi_GetVolumeAsync
393
394 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 7.
395 The buffer should not be used for other purposes until the asynchronous process completes, as results are written to the results buffer asynchronously from the function call.
396
397 Arguments: volume: Buffer used to get the volume information
398 callback: Callback function that notifies of the results when the asynchronous processing is completed.
399 arg: Parameter passed to the callback function
400 eightlv: Gets the volume as one of eight levels
401 keep: Gets the amount of volume reserved for changes in volume. If there is no amount reserved, gets the current value.
402
403 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
404 *---------------------------------------------------------------------------
405
406
407
408 */
409 SNDEXResult
SNDEXi_GetVolumeAsync(u8 * volume,SNDEXCallback callback,void * arg,BOOL eightlv,BOOL keep)410 SNDEXi_GetVolumeAsync (u8* volume, SNDEXCallback callback, void* arg, BOOL eightlv, BOOL keep)
411 {
412 /* No parameter restrictions */
413
414 /* Confirm status */
415 {
416 SNDEXResult result = CheckState();
417 if (result != SNDEX_RESULT_SUCCESS)
418 {
419 return result;
420 }
421 }
422
423 /* Register asynchronous process */
424 SetSndexWork(callback, arg, (void*)volume, SNDEX_PXI_COMMAND_GET_VOLUME);
425
426 /* Issue command to ARM7 */
427 if (FALSE == SendCommand(sndexWork.command,
428 (u8)((keep << SNDEX_PXI_PARAMETER_SHIFT_VOL_KEEP) | (eightlv << SNDEX_PXI_PARAMETER_SHIFT_VOL_8LV))))
429 {
430 return SNDEX_RESULT_PXI_SEND_ERROR;
431 }
432 return SNDEX_RESULT_SUCCESS;
433 }
434
435 /*---------------------------------------------------------------------------*
436 Name: SNDEXi_GetVolume
437
438 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 7.
439 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
440
441 Arguments: volume: Buffer used to get the volume information
442 eightlv: Gets the volume as one of eight levels
443 keep: Gets the amount of volume reserved for changes in volume. If there is no amount reserved, gets the current value.
444
445 Returns: SNDEXResult: Returns processing results.
446 *---------------------------------------------------------------------------*/
447 SNDEXResult
SNDEXi_GetVolume(u8 * volume,BOOL eightlv,BOOL keep)448 SNDEXi_GetVolume (u8* volume, BOOL eightlv, BOOL keep)
449 {
450 SNDEXResult result;
451 OSMessageQueue msgQ;
452 OSMessage msg[1];
453
454 /* Calling this from an exception handler is prohibited */
455 if (OS_GetCurrentThread() == NULL)
456 {
457 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
458 return SNDEX_RESULT_ILLEGAL_STATE;
459 }
460
461 /* Initialize the message queue used for synchronization */
462 OS_InitMessageQueue(&msgQ, msg, 1);
463
464 /* Execute the asynchronous function and idle the callback */
465 result = SNDEXi_GetVolumeAsync(volume, SyncCallback, (void*)(&msgQ), eightlv, keep);
466 if (result == SNDEX_RESULT_SUCCESS)
467 {
468 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
469 }
470 return result;
471 }
472
473 /*---------------------------------------------------------------------------*
474 Name: SNDEXi_GetVolumeExAsync
475
476 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 31.
477 The buffer should not be used for other purposes until the asynchronous process completes, as results are written to the results buffer asynchronously from the function call.
478
479 Arguments: volume: Buffer used to get the volume information
480 callback: Callback function that notifies of the results when the asynchronous processing is completed.
481 arg: Parameter passed to the callback function
482
483 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
484 *---------------------------------------------------------------------------
485
486
487
488 */
489 SNDEXResult
SNDEXi_GetVolumeExAsync(u8 * volume,SNDEXCallback callback,void * arg)490 SNDEXi_GetVolumeExAsync (u8* volume, SNDEXCallback callback, void* arg)
491 {
492 if (!OS_IsRunOnTwl())
493 {
494 return SNDEX_RESULT_ILLEGAL_STATE;
495 }
496
497 return SNDEXi_GetVolumeAsync(volume, callback, arg, FALSE, TRUE);
498 }
499
500 /*---------------------------------------------------------------------------*
501 Name: SNDEXi_GetVolumeEx
502
503 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 31.
504 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
505
506 Arguments: volume: Buffer used to get the volume information
507
508 Returns: SNDEXResult: Returns processing results.
509 *---------------------------------------------------------------------------*/
510 SNDEXResult
SNDEXi_GetVolumeEx(u8 * volume)511 SNDEXi_GetVolumeEx (u8* volume)
512 {
513 if (!OS_IsRunOnTwl())
514 {
515 return SNDEX_RESULT_ILLEGAL_STATE;
516 }
517
518 return SNDEXi_GetVolume(volume, FALSE, TRUE);
519 }
520
521 /*---------------------------------------------------------------------------*
522 Name: SNDEXi_GetCurrentVolumeEx[Async]
523
524 Description: Gets the audio output volume information. Minimum volume: 0, maximum: 31.
525 If this is the synchronous function, calling it from inside an interrupt handler is prohibited.
526 For asynchronous functions, the buffer should not be used for other purposes until the asynchronous process completes, as results are written to the results buffer asynchronously from the function call.
527
528 Arguments: volume: Buffer used to get the volume information
529 [callback: Callback function that notifies the results when the asynchronous processing is completed]
530 [arg: Parameter passed to the callback function]
531
532 Returns: SNDEXResult: Returns processing results.
533 *---------------------------------------------------------------------------
534 */
535 SNDEXResult
SNDEXi_GetCurrentVolumeExAsync(u8 * volume,SNDEXCallback callback,void * arg)536 SNDEXi_GetCurrentVolumeExAsync (u8* volume, SNDEXCallback callback, void* arg)
537 {
538 if (!OS_IsRunOnTwl())
539 {
540 return SNDEX_RESULT_ILLEGAL_STATE;
541 }
542
543 return SNDEXi_GetVolumeAsync(volume, callback, arg, FALSE, FALSE);
544 }
545
546 SNDEXResult
SNDEXi_GetCurrentVolumeEx(u8 * volume)547 SNDEXi_GetCurrentVolumeEx (u8* volume)
548 {
549 if (!OS_IsRunOnTwl())
550 {
551 return SNDEX_RESULT_ILLEGAL_STATE;
552 }
553
554 return SNDEXi_GetVolume(volume, FALSE, FALSE);
555 }
556
557 /*---------------------------------------------------------------------------*
558 Name: SNDEXi_GetDeviceAsync
559
560 Description: Gets the audio output device setting information.
561 The buffer should not be used for other purposes until the asynchronous process completes, as results are written to the results buffer asynchronously from the function call.
562
563 Arguments: device: Buffer used to get the output device information
564 callback: Callback function that notifies of the results when the asynchronous processing is completed.
565 arg: Parameter passed to the callback function
566
567 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
568 *---------------------------------------------------------------------------
569
570
571
572 */
573 SNDEXResult
SNDEXi_GetDeviceAsync(SNDEXDevice * device,SNDEXCallback callback,void * arg)574 SNDEXi_GetDeviceAsync (SNDEXDevice* device, SNDEXCallback callback, void* arg)
575 {
576 /* No parameter restrictions */
577
578 /* Confirm status */
579 {
580 SNDEXResult result = CheckState();
581 if (result != SNDEX_RESULT_SUCCESS)
582 {
583 return result;
584 }
585 }
586
587 /* Register asynchronous process */
588 SetSndexWork(callback, arg, (void*)device, SNDEX_PXI_COMMAND_GET_SND_DEVICE);
589
590 /* Issue command to ARM7 */
591 if (FALSE == SendCommand(sndexWork.command, 0))
592 {
593 return SNDEX_RESULT_PXI_SEND_ERROR;
594 }
595 return SNDEX_RESULT_SUCCESS;
596 }
597
598 /*---------------------------------------------------------------------------*
599 Name: SNDEXi_GetDevice
600
601 Description: Gets the audio output device setting information.
602 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
603
604 Arguments: device: Buffer used to get the output device information
605
606 Returns: SNDEXResult: Returns processing results.
607 *---------------------------------------------------------------------------*/
608 SNDEXResult
SNDEXi_GetDevice(SNDEXDevice * device)609 SNDEXi_GetDevice (SNDEXDevice* device)
610 {
611 SNDEXResult result;
612 OSMessageQueue msgQ;
613 OSMessage msg[1];
614
615 /* Calling this from an exception handler is prohibited */
616 if (OS_GetCurrentThread() == NULL)
617 {
618 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
619 return SNDEX_RESULT_ILLEGAL_STATE;
620 }
621
622 /* Initialize the message queue used for synchronization */
623 OS_InitMessageQueue(&msgQ, msg, 1);
624
625 /* Execute the asynchronous function and idle the callback */
626 result = SNDEXi_GetDeviceAsync(device, SyncCallback, (void*)(&msgQ));
627 if (result == SNDEX_RESULT_SUCCESS)
628 {
629 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
630 }
631 return result;
632 }
633
634 /*---------------------------------------------------------------------------*
635 Name: SNDEXi_SetMuteAsync
636
637 Description: Changes the mute status of the audio output.
638
639 Arguments: mute: Mute setting status
640 callback: Callback function that notifies of the results when the asynchronous processing is completed.
641 arg: Parameter passed to the callback function
642
643 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
644 *---------------------------------------------------------------------------
645
646
647 */
648 SNDEXResult
SNDEXi_SetMuteAsync(SNDEXMute mute,SNDEXCallback callback,void * arg)649 SNDEXi_SetMuteAsync (SNDEXMute mute, SNDEXCallback callback, void* arg)
650 {
651 /* Parameter restriction check */
652 if (mute >= SNDEX_MUTE_MAX)
653 {
654 SNDEXi_Warning("%s: Invalid parameter (mute: %d)\n", __FUNCTION__, mute);
655 return SNDEX_RESULT_INVALID_PARAM;
656 }
657
658 /* Confirm status */
659 {
660 SNDEXResult result = CheckState();
661 if (result != SNDEX_RESULT_SUCCESS)
662 {
663 return result;
664 }
665 }
666
667 /* Register asynchronous process */
668 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_SMIX_MUTE);
669
670 /* Issue command to ARM7 */
671 if (FALSE == SendCommand(sndexWork.command, (u8)mute))
672 {
673 return SNDEX_RESULT_PXI_SEND_ERROR;
674 }
675 return SNDEX_RESULT_SUCCESS;
676 }
677
678 /*---------------------------------------------------------------------------*
679 Name: SNDEXi_SetMute
680
681 Description: Changes the mute status of the audio output.
682 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
683
684 Arguments: mute: Mute setting status
685
686 Returns: SNDEXResult: Returns processing results.
687 *---------------------------------------------------------------------------*/
688 SNDEXResult
SNDEXi_SetMute(SNDEXMute mute)689 SNDEXi_SetMute (SNDEXMute mute)
690 {
691 SNDEXResult result;
692 OSMessageQueue msgQ;
693 OSMessage msg[1];
694
695 /* Calling this from an exception handler is prohibited */
696 if (OS_GetCurrentThread() == NULL)
697 {
698 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
699 return SNDEX_RESULT_ILLEGAL_STATE;
700 }
701
702 /* Initialize the message queue used for synchronization */
703 OS_InitMessageQueue(&msgQ, msg, 1);
704
705 /* Execute the asynchronous function and idle the callback */
706 result = SNDEXi_SetMuteAsync(mute, SyncCallback, (void*)(&msgQ));
707 if (result == SNDEX_RESULT_SUCCESS)
708 {
709 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
710 }
711 return result;
712 }
713
714 /*---------------------------------------------------------------------------*
715 Name: SNDEXi_SetI2SFrequencyAsync
716
717 Description: Changes the I2S frequency.
718
719 Arguments: freq: Frequency
720 callback: Callback function that notifies of the results when the asynchronous processing is completed.
721 arg: Parameter passed to the callback function
722
723 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
724 *---------------------------------------------------------------------------
725
726
727 */
728 SNDEXResult
SNDEXi_SetI2SFrequencyAsync(SNDEXFrequency freq,SNDEXCallback callback,void * arg)729 SNDEXi_SetI2SFrequencyAsync (SNDEXFrequency freq, SNDEXCallback callback, void* arg)
730 {
731 /* Parameter restriction check */
732 if (freq >= SNDEX_FREQUENCY_MAX)
733 {
734 SNDEXi_Warning("%s: Invalid parameter (freq: %d)\n", __FUNCTION__, freq);
735 return SNDEX_RESULT_INVALID_PARAM;
736 }
737
738 /* Check CODEC operating mode */
739 if (OSi_IsCodecTwlMode() == FALSE)
740 {
741 return SNDEX_RESULT_ILLEGAL_STATE;
742 }
743
744 /* Confirm status */
745 {
746 SNDEXResult result = CheckState();
747 if (result != SNDEX_RESULT_SUCCESS)
748 {
749 return result;
750 }
751 }
752
753 /* Register asynchronous process */
754 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_SMIX_FREQ);
755
756 /* Issue command to ARM7 */
757 if (FALSE == SendCommand(sndexWork.command, (u8)freq))
758 {
759 return SNDEX_RESULT_PXI_SEND_ERROR;
760 }
761 return SNDEX_RESULT_SUCCESS;
762 }
763
764 /*---------------------------------------------------------------------------*
765 Name: SNDEXi_SetI2SFrequency
766
767 Description: Changes the I2S frequency.
768 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
769
770 Arguments: freq: Frequency
771
772 Returns: SNDEXResult: Returns processing results.
773 *---------------------------------------------------------------------------*/
774 SNDEXResult
SNDEXi_SetI2SFrequency(SNDEXFrequency freq)775 SNDEXi_SetI2SFrequency (SNDEXFrequency freq)
776 {
777 SNDEXResult result;
778 OSMessageQueue msgQ;
779 OSMessage msg[1];
780
781 /* Calling this from an exception handler is prohibited */
782 if (OS_GetCurrentThread() == NULL)
783 {
784 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
785 return SNDEX_RESULT_ILLEGAL_STATE;
786 }
787
788 /* Initialize the message queue used for synchronization */
789 OS_InitMessageQueue(&msgQ, msg, 1);
790
791 /* Execute the asynchronous function and idle the callback */
792 result = SNDEXi_SetI2SFrequencyAsync(freq, SyncCallback, (void*)(&msgQ));
793 if (result == SNDEX_RESULT_SUCCESS)
794 {
795 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
796 }
797 return result;
798 }
799
800 /*---------------------------------------------------------------------------*
801 Name: SNDEXi_SetDSPMixRateAsync
802
803 Description: Changes the audio output mix rate for the CPU and DSP.
804 Minimum mix rate: 0 (DSP 100%), maximum: 8 (CPU 100%).
805
806 Arguments: rate: Mix rate with a numeral from 0 to 8
807 callback: Callback function that notifies of the results when the asynchronous processing is completed.
808 arg: Parameter passed to the callback function
809
810 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
811 *---------------------------------------------------------------------------
812
813
814 */
815 SNDEXResult
SNDEXi_SetDSPMixRateAsync(u8 rate,SNDEXCallback callback,void * arg)816 SNDEXi_SetDSPMixRateAsync (u8 rate, SNDEXCallback callback, void* arg)
817 {
818 /* Check CODEC operating mode */
819 if (OSi_IsCodecTwlMode() == FALSE)
820 {
821 SNDEXi_Warning("%s: Illegal state\n", __FUNCTION__);
822 return SNDEX_RESULT_ILLEGAL_STATE;
823 }
824
825 /* Parameter restriction check */
826 if (rate > SNDEX_DSP_MIX_RATE_MAX)
827 {
828 SNDEXi_Warning("%s: Invalid parameter (rate: %u)\n", __FUNCTION__, rate);
829 return SNDEX_RESULT_INVALID_PARAM;
830 }
831
832 /* Confirm status */
833 {
834 SNDEXResult result = CheckState();
835 if (result != SNDEX_RESULT_SUCCESS)
836 {
837 return result;
838 }
839 }
840
841 /* Register asynchronous process */
842 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_SMIX_DSP);
843
844 /* Issue command to ARM7 */
845 if (FALSE == SendCommand(sndexWork.command, (u8)rate))
846 {
847 return SNDEX_RESULT_PXI_SEND_ERROR;
848 }
849 return SNDEX_RESULT_SUCCESS;
850 }
851
852 /*---------------------------------------------------------------------------*
853 Name: SNDEXi_SetDSPMixRate
854
855 Description: Changes the audio output mix rate for the CPU and DSP.
856 Minimum mix rate: 0 (DSP 100%), maximum: 8 (CPU 100%).
857 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
858
859 Arguments: rate: Mix rate with a numeral from 0 to 8
860
861 Returns: SNDEXResult: Returns processing results.
862 *---------------------------------------------------------------------------*/
863 SNDEXResult
SNDEXi_SetDSPMixRate(u8 rate)864 SNDEXi_SetDSPMixRate (u8 rate)
865 {
866 SNDEXResult result;
867 OSMessageQueue msgQ;
868 OSMessage msg[1];
869
870 /* Calling this from an exception handler is prohibited */
871 if (OS_GetCurrentThread() == NULL)
872 {
873 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
874 return SNDEX_RESULT_ILLEGAL_STATE;
875 }
876
877 /* Initialize the message queue used for synchronization */
878 OS_InitMessageQueue(&msgQ, msg, 1);
879
880 /* Execute the asynchronous function and idle the callback */
881 result = SNDEXi_SetDSPMixRateAsync(rate, SyncCallback, (void*)(&msgQ));
882 if (result == SNDEX_RESULT_SUCCESS)
883 {
884 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
885 }
886 return result;
887 }
888
889 /*---------------------------------------------------------------------------*
890 Name: SNDEXi_SetVolumeAsync
891
892 Description: Changes the audio output volume. Minimum volume: 0, maximum: 7.
893
894 Arguments: volume: Volume as a numeral from 0 to 7
895 callback: Callback function that notifies of the results when the asynchronous processing is completed.
896 arg: Parameter passed to the callback function
897 eightlv: Sets the volume as one of eight levels
898
899 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
900 *---------------------------------------------------------------------------
901
902
903 */
904 SNDEXResult
SNDEXi_SetVolumeAsync(u8 volume,SNDEXCallback callback,void * arg,BOOL eightlv)905 SNDEXi_SetVolumeAsync (u8 volume, SNDEXCallback callback, void* arg, BOOL eightlv)
906 {
907 /* Parameter restriction check */
908 if (volume > (eightlv ? SNDEX_VOLUME_MAX : SNDEX_VOLUME_MAX_EX))
909 {
910 SNDEXi_Warning("%s: Invalid parameter (volume: %u)\n", __FUNCTION__, volume);
911 return SNDEX_RESULT_INVALID_PARAM;
912 }
913
914 /* Confirm status */
915 {
916 SNDEXResult result = CheckState();
917 if (result != SNDEX_RESULT_SUCCESS)
918 {
919 return result;
920 }
921 }
922
923 /* Register asynchronous process */
924 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_VOLUME);
925
926 /* Issue command to ARM7 */
927 if (FALSE == SendCommand(sndexWork.command,
928 (u8)((eightlv << SNDEX_PXI_PARAMETER_SHIFT_VOL_8LV) | (SNDEX_PXI_PARAMETER_MASK_VOL_VALUE & volume))))
929 {
930 return SNDEX_RESULT_PXI_SEND_ERROR;
931 }
932 return SNDEX_RESULT_SUCCESS;
933 }
934
935 /*---------------------------------------------------------------------------*
936 Name: SNDEXi_SetVolume
937
938 Description: Changes the audio output volume. Minimum volume: 0, maximum: 7.
939 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
940
941 Arguments: volume: Volume as a numeral from 0 to 7
942
943 Returns: SNDEXResult: Returns processing results.
944 *---------------------------------------------------------------------------*/
945 SNDEXResult
SNDEXi_SetVolume(u8 volume,BOOL eightlv)946 SNDEXi_SetVolume (u8 volume, BOOL eightlv)
947 {
948 SNDEXResult result;
949 OSMessageQueue msgQ;
950 OSMessage msg[1];
951
952 /* Calling this from an exception handler is prohibited */
953 if (OS_GetCurrentThread() == NULL)
954 {
955 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
956 return SNDEX_RESULT_ILLEGAL_STATE;
957 }
958
959 /* Initialize the message queue used for synchronization */
960 OS_InitMessageQueue(&msgQ, msg, 1);
961
962 /* Execute the asynchronous function and idle the callback */
963 result = SNDEXi_SetVolumeAsync(volume, SyncCallback, (void*)(&msgQ), eightlv);
964 if (result == SNDEX_RESULT_SUCCESS)
965 {
966 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
967 }
968 return result;
969 }
970
971 /*---------------------------------------------------------------------------*
972 Name: SNDEXi_SetVolumeExAsync
973
974 Description: Changes the audio output volume. Minimum volume: 0, maximum: 31.
975
976 Arguments: volume: Volume as a numeral from 0 to 31
977 callback: Callback function that notifies of the results when the asynchronous processing is completed.
978 arg: Parameter passed to the callback function
979
980 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
981 *---------------------------------------------------------------------------
982
983
984 */
985 SNDEXResult
SNDEXi_SetVolumeExAsync(u8 volume,SNDEXCallback callback,void * arg)986 SNDEXi_SetVolumeExAsync (u8 volume, SNDEXCallback callback, void* arg)
987 {
988 if (!OS_IsRunOnTwl())
989 {
990 return SNDEX_RESULT_ILLEGAL_STATE;
991 }
992
993 return SNDEXi_SetVolumeAsync(volume, callback, arg, FALSE);
994 }
995
996 /*---------------------------------------------------------------------------*
997 Name: SNDEXi_SetVolumeEx
998
999 Description: Changes the audio output volume. Minimum volume: 0, maximum: 31.
1000 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
1001
1002 Arguments: volume: Volume as a numeral from 0 to 31
1003
1004 Returns: SNDEXResult: Returns processing results.
1005 *---------------------------------------------------------------------------*/
1006 SNDEXResult
SNDEXi_SetVolumeEx(u8 volume)1007 SNDEXi_SetVolumeEx (u8 volume)
1008 {
1009 if (!OS_IsRunOnTwl())
1010 {
1011 return SNDEX_RESULT_ILLEGAL_STATE;
1012 }
1013
1014 return SNDEXi_SetVolume(volume, FALSE);
1015 }
1016
1017 /*---------------------------------------------------------------------------*
1018 Name: SNDEXi_SetDeviceAsync
1019
1020 Description: Changes the audio output device setting.
1021
1022 Arguments: device: Output device setting
1023 callback: Callback function that notifies of the results when the asynchronous processing is completed.
1024 arg: Parameter passed to the callback function
1025
1026 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
1027 *---------------------------------------------------------------------------
1028
1029
1030 */
1031 SNDEXResult
SNDEXi_SetDeviceAsync(SNDEXDevice device,SNDEXCallback callback,void * arg)1032 SNDEXi_SetDeviceAsync (SNDEXDevice device, SNDEXCallback callback, void* arg)
1033 {
1034 /* Parameter restriction check */
1035 if (device >= SNDEX_DEVICE_MAX)
1036 {
1037 SNDEXi_Warning("%s: Invalid parameter (device: %d)\n", __FUNCTION__, device);
1038 return SNDEX_RESULT_INVALID_PARAM;
1039 }
1040
1041 /* Check CODEC operating mode */
1042 if (OSi_IsCodecTwlMode() == FALSE)
1043 {
1044 return SNDEX_RESULT_ILLEGAL_STATE;
1045 }
1046
1047 /* Confirm status */
1048 {
1049 SNDEXResult result = CheckState();
1050 if (result != SNDEX_RESULT_SUCCESS)
1051 {
1052 return result;
1053 }
1054 }
1055
1056 /* Register asynchronous process */
1057 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_SND_DEVICE);
1058
1059 /* Issue command to ARM7 */
1060 if (FALSE == SendCommand(sndexWork.command, (u8)device))
1061 {
1062 return SNDEX_RESULT_PXI_SEND_ERROR;
1063 }
1064 return SNDEX_RESULT_SUCCESS;
1065 }
1066
1067 /*---------------------------------------------------------------------------*
1068 Name: SNDEXi_SetDevice
1069
1070 Description: Changes the audio output device setting.
1071 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
1072
1073 Arguments: device: Output device setting
1074
1075 Returns: SNDEXResult: Returns processing results.
1076 *---------------------------------------------------------------------------*/
1077 SNDEXResult
SNDEXi_SetDevice(SNDEXDevice device)1078 SNDEXi_SetDevice (SNDEXDevice device)
1079 {
1080 SNDEXResult result;
1081 OSMessageQueue msgQ;
1082 OSMessage msg[1];
1083
1084 /* Calling this from an exception handler is prohibited */
1085 if (OS_GetCurrentThread() == NULL)
1086 {
1087 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1088 return SNDEX_RESULT_ILLEGAL_STATE;
1089 }
1090
1091 /* Initialize the message queue used for synchronization */
1092 OS_InitMessageQueue(&msgQ, msg, 1);
1093
1094 /* Execute the asynchronous function and idle the callback */
1095 result = SNDEXi_SetDeviceAsync(device, SyncCallback, (void*)(&msgQ));
1096 if (result == SNDEX_RESULT_SUCCESS)
1097 {
1098 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1099 }
1100 return result;
1101 }
1102
1103 /*---------------------------------------------------------------------------*
1104 Name: SNDEX_SetIirFilterAsync
1105
1106 Description: Asynchronously sets the IIR filter (Biquad) parameters.
1107
1108 !! CAUTION!!: This uses multiple back-to-back transfers, as it is not possible to pass all parameters to ARM7 in one PXI transmission. Just sending all parameters in successive transmissions could run into problems where the previous parameter has not been fully processed when the next arrives, so this waits for processing to complete before making the next PXI transmission.
1109
1110 Arguments: target:
1111 pParam:
1112
1113 Returns: None.
1114 *---------------------------------------------------------------------------
1115
1116
1117 */
1118 SNDEXResult
SNDEXi_SetIirFilterAsync(SNDEXIirFilterTarget target,const SNDEXIirFilterParam * pParam,SNDEXCallback callback,void * arg)1119 SNDEXi_SetIirFilterAsync(SNDEXIirFilterTarget target, const SNDEXIirFilterParam* pParam, SNDEXCallback callback, void* arg)
1120 {
1121 /* target range check */
1122 if ( target < 0 || target >= SNDEX_IIR_FILTER_TARGET_AVAILABLE_MAX )
1123 {
1124 return SNDEX_RESULT_ILLEGAL_TARGET;
1125 }
1126
1127 // Return an error if already processing SetIirFilterAsync
1128 if (isIirFilterSetting)
1129 {
1130 return SNDEX_RESULT_EXCLUSIVE;
1131 }
1132 isIirFilterSetting = TRUE;
1133
1134 /* Check CODEC operating mode */
1135 if (OSi_IsCodecTwlMode() == FALSE)
1136 {
1137 SNDEXi_Warning("%s: Illegal state\n", __FUNCTION__);
1138 isIirFilterSetting = FALSE;
1139 return SNDEX_RESULT_ILLEGAL_STATE;
1140 }
1141
1142 /* Confirm status */
1143 {
1144 SNDEXResult result = CheckState();
1145 if (result != SNDEX_RESULT_SUCCESS)
1146 {
1147 isIirFilterSetting = FALSE;
1148 return result;
1149 }
1150 }
1151
1152 /* Target */
1153 /* Register asynchronous process */
1154 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_TARGET);
1155 /* Issue command to ARM7 */
1156 if (FALSE == SendCommandEx(sndexWork.command, (u16)target))
1157 {
1158 isIirFilterSetting = FALSE;
1159 return SNDEX_RESULT_PXI_SEND_ERROR;
1160 }
1161 // Wait for the callback by idling in an empty loop so that there is time for the CheckState function's Warning suppression
1162 OS_SpinWait(67 * 1000); //Approximately 1 ms
1163
1164 // Wait until the previous PXI transfer's processing ends
1165 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1166 {
1167 OS_SpinWait(67 * 1000); //Approximately 1 ms
1168 }
1169
1170 /* Filter parameter */
1171 // n0
1172 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N0);
1173 /* Issue command to ARM7 */
1174 if (FALSE == SendCommandEx(sndexWork.command, pParam->n0))
1175 {
1176 isIirFilterSetting = FALSE;
1177 return SNDEX_RESULT_PXI_SEND_ERROR;
1178 }
1179 OS_SpinWait(67 * 1000); //Approximately 1 ms
1180
1181 // Wait until the previous PXI transfer's processing ends
1182 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1183 {
1184 OS_SpinWait(67 * 1000); //Approximately 1 ms
1185 }
1186
1187 // n1
1188 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N1);
1189 /* Issue command to ARM7 */
1190 if (FALSE == SendCommandEx(sndexWork.command, pParam->n1))
1191 {
1192 isIirFilterSetting = FALSE;
1193 return SNDEX_RESULT_PXI_SEND_ERROR;
1194 }
1195 OS_SpinWait(67 * 1000); //Approximately 1 ms
1196
1197 // Wait until the previous PXI transfer's processing ends
1198 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1199 {
1200 OS_SpinWait(67 * 1000); //Approximately 1 ms
1201 }
1202
1203 // n2
1204 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N2);
1205 /* Issue command to ARM7 */
1206 if (FALSE == SendCommandEx(sndexWork.command, pParam->n2))
1207 {
1208 isIirFilterSetting = FALSE;
1209 return SNDEX_RESULT_PXI_SEND_ERROR;
1210 }
1211 OS_SpinWait(67 * 1000); //Approximately 1 ms
1212
1213 // Wait until the previous PXI transfer's processing ends
1214 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1215 {
1216 OS_SpinWait(67 * 1000); //Approximately 1 ms
1217 }
1218
1219 // d1
1220 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_D1);
1221 /* Issue command to ARM7 */
1222 if (FALSE == SendCommandEx(sndexWork.command, pParam->d1))
1223 {
1224 isIirFilterSetting = FALSE;
1225 return SNDEX_RESULT_PXI_SEND_ERROR;
1226 }
1227 OS_SpinWait(67 * 1000); //Approximately 1 ms
1228
1229 // Wait until the previous PXI transfer's processing ends
1230 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1231 {
1232 OS_SpinWait(67 * 1000); //Approximately 1 ms
1233 }
1234
1235 // d2
1236 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_D2);
1237 /* Issue command to ARM7 */
1238 if (FALSE == SendCommandEx(sndexWork.command, pParam->d2))
1239 {
1240 isIirFilterSetting = FALSE;
1241 return SNDEX_RESULT_PXI_SEND_ERROR;
1242 }
1243 OS_SpinWait(67 * 1000); //Approximately 1 ms
1244
1245 // Wait until the previous PXI transfer's processing ends
1246 while ( CheckState() != SNDEX_RESULT_SUCCESS )
1247 {
1248 OS_SpinWait(67 * 1000); //Approximately 1 ms
1249 }
1250
1251 /* Set the target and the filter parameters */
1252 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER);
1253 /* Issue command to ARM7 */
1254 if (FALSE == SendCommandEx(sndexWork.command, 0))
1255 {
1256 isIirFilterSetting = FALSE;
1257 return SNDEX_RESULT_PXI_SEND_ERROR;
1258 }
1259
1260 return SNDEX_RESULT_SUCCESS;
1261 }
1262
1263 /*---------------------------------------------------------------------------*
1264 Name: SNDEXi_SetIirFilter
1265
1266 Description: Sets the IIR filter (Biquad) parameters.
1267
1268 Arguments: target:
1269 pParam:
1270
1271 Returns: None.
1272 *---------------------------------------------------------------------------*/
1273 SNDEXResult
SNDEXi_SetIirFilter(SNDEXIirFilterTarget target,const SNDEXIirFilterParam * pParam)1274 SNDEXi_SetIirFilter(SNDEXIirFilterTarget target, const SNDEXIirFilterParam* pParam)
1275 {
1276 SNDEXResult result;
1277 OSMessageQueue msgQ;
1278 OSMessage msg[1];
1279
1280 /* Calling this from an exception handler is prohibited */
1281 if (OS_GetCurrentThread() == NULL)
1282 {
1283 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1284 return SNDEX_RESULT_ILLEGAL_STATE;
1285 }
1286
1287 /* target range check */
1288 if ( target < 0 || target >= SNDEX_IIR_FILTER_TARGET_AVAILABLE_MAX )
1289 {
1290 return SNDEX_RESULT_ILLEGAL_TARGET;
1291 }
1292
1293 /* Initialize the message queue used for synchronization */
1294 OS_InitMessageQueue(&msgQ, msg, 1);
1295
1296 result = SNDEXi_SetIirFilterAsync(target, pParam, SyncCallback, (void*)(&msgQ));
1297 if (result == SNDEX_RESULT_SUCCESS)
1298 {
1299 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1300 }
1301
1302 // Assume that the SPI_Lock was ended by SetIirFilter, and clear the flag
1303 isLockSpi = FALSE;
1304
1305 isIirFilterSetting = FALSE;
1306
1307 return result;
1308 }
1309
1310 /*---------------------------------------------------------------------------*
1311 Name: SNDEX_IsConnectedHeadphoneAsync
1312
1313 Description: Gets whether headphones are connected.
1314
1315 Arguments: hp: Buffer used to get headphone connection status
1316 callback: Callback function that notifies of the results when the asynchronous processing is completed.
1317 arg: Parameter passed to the callback function
1318
1319 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
1320 *---------------------------------------------------------------------------
1321
1322
1323 */
1324 SNDEXResult
SNDEXi_IsConnectedHeadphoneAsync(SNDEXHeadphone * hp,SNDEXCallback callback,void * arg)1325 SNDEXi_IsConnectedHeadphoneAsync(SNDEXHeadphone *hp, SNDEXCallback callback, void* arg)
1326 {
1327 /* Confirm status */
1328 {
1329 SNDEXResult result = CheckState();
1330 if (result != SNDEX_RESULT_SUCCESS)
1331 {
1332 return result;
1333 }
1334 }
1335
1336 /* Register asynchronous process */
1337 SetSndexWork(callback, arg, (void*)hp, SNDEX_PXI_COMMAND_HP_CONNECT);
1338
1339 /* Issue command to ARM7 */
1340 if (FALSE == SendCommand(sndexWork.command, 0))
1341 {
1342 return SNDEX_RESULT_PXI_SEND_ERROR;
1343 }
1344 return SNDEX_RESULT_SUCCESS;
1345 }
1346
1347 /*---------------------------------------------------------------------------*
1348 Name: SNDEX_IsConnectedHeadphone
1349
1350 Description: Gets whether headphones are connected.�B
1351
1352 Arguments: hp: Buffer used to get headphone connection status
1353
1354 Returns: SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the function registered to the callback is notified of the actual processing results after the asynchronous process is complete.
1355 *---------------------------------------------------------------------------
1356
1357 */
1358 SNDEXResult
SNDEXi_IsConnectedHeadphone(SNDEXHeadphone * hp)1359 SNDEXi_IsConnectedHeadphone(SNDEXHeadphone *hp)
1360 {
1361 SNDEXResult result;
1362 OSMessageQueue msgQ;
1363 OSMessage msg[1];
1364
1365 /* Calling this from an exception handler is prohibited */
1366 if (OS_GetCurrentThread() == NULL)
1367 {
1368 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1369 return SNDEX_RESULT_ILLEGAL_STATE;
1370 }
1371
1372 /* Initialize the message queue used for synchronization */
1373 OS_InitMessageQueue(&msgQ, msg, 1);
1374
1375 /* Execute the asynchronous function and idle the callback */
1376 result = SNDEXi_IsConnectedHeadphoneAsync(hp, SyncCallback, (void*)(&msgQ));
1377 if (result == SNDEX_RESULT_SUCCESS)
1378 {
1379 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1380 }
1381 return result;
1382 }
1383
1384 /*---------------------------------------------------------------------------*
1385 Name: SNDEXi_SetVolumeSwitchCallback
1386
1387 Description: Sets the callback function that is called when the volume button is pressed.
1388
1389 Arguments: callback: Callback function called when the volume button is pressed
1390 arg: Parameter passed to the callback function
1391
1392 Returns: None.
1393 *---------------------------------------------------------------------------*/
SNDEXi_SetVolumeSwitchCallback(SNDEXCallback callback,void * arg)1394 void SNDEXi_SetVolumeSwitchCallback(SNDEXCallback callback, void* arg)
1395 {
1396 SNDEXi_VolumeSwitchCallbackInfo.callback = callback;
1397 SNDEXi_VolumeSwitchCallbackInfo.cbArg = arg;
1398 }
1399
1400 /*---------------------------------------------------------------------------*
1401 Name: SNDEXi_SetIgnoreHWVolume
1402
1403 Description: If you need to play a sound (such as the clock's alarm tone) at a specified volume regardless of the value set for the system volume at the time, you must change the volume without user input.
1404 This function saves the volume before changing it.
1405
1406 Arguments: volume: Value to change the volume to
1407
1408 Returns: SNDEXResult: Returns processing results. This is the result of an SNDEX function called internally.
1409 *---------------------------------------------------------------------------
1410
1411 */
SNDEXi_SetIgnoreHWVolume(u8 volume,BOOL eightlv)1412 SNDEXResult SNDEXi_SetIgnoreHWVolume(u8 volume, BOOL eightlv)
1413 {
1414 SNDEXResult result;
1415
1416 // If the ResetIgnoreHWVolume function was not run after the previous SetIgnoreHWVolume function was called, the volume value is not saved.
1417 //
1418 if (!isStoreVolume)
1419 {
1420 result = SNDEXi_GetVolumeEx(&storeVolume);
1421 if (result != SNDEX_RESULT_SUCCESS)
1422 {
1423 return result;
1424 }
1425 }
1426
1427 // Change the volume to the specified value
1428 result = eightlv ? SNDEX_SetVolume(volume) : SNDEXi_SetVolumeEx(volume);
1429 if (result != SNDEX_RESULT_SUCCESS)
1430 {
1431 return result;
1432 }
1433
1434 isStoreVolume = TRUE;
1435 return result; // SNDEX_RESULT_SUCCESS
1436 }
1437
1438 /*---------------------------------------------------------------------------*
1439 Name: SNDEXi_ResetIgnoreHWVolume
1440
1441 Description: Restores the volume to its value before changed by SNDEX_SetIgnoreHWVolume.
1442
1443 Arguments: None.
1444
1445 Returns: SNDEXResult: Returns processing results.
1446 *---------------------------------------------------------------------------*/
SNDEXi_ResetIgnoreHWVolume(void)1447 SNDEXResult SNDEXi_ResetIgnoreHWVolume(void)
1448 {
1449 SNDEXResult result;
1450 if ((result = SNDEXi_SetVolumeEx(storeVolume)) != SNDEX_RESULT_SUCCESS)
1451 {
1452 return result;
1453 }
1454
1455 isStoreVolume = FALSE;
1456 return result; // SNDEX_RESULT_SUCCESS
1457 }
1458
1459 /*---------------------------------------------------------------------------*
1460 Name: SNDEXi_PreProcessForShutterSound
1461
1462 Description: Performs all the preprocessing necessary for shutter sound playback.
1463 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
1464
1465 Arguments: None.
1466
1467 Returns: Returns SNDEX_RESULT_SUCCESS if successful.
1468 *---------------------------------------------------------------------------*/
1469 SNDEXResult
SNDEXi_PreProcessForShutterSound(void)1470 SNDEXi_PreProcessForShutterSound (void)
1471 {
1472 SNDEXResult result;
1473 OSMessageQueue msgQ;
1474 OSMessage msg[1];
1475
1476 /* Check CODEC operating mode */
1477 if (OSi_IsCodecTwlMode() == FALSE)
1478 {
1479 return SNDEX_RESULT_ILLEGAL_STATE;
1480 }
1481
1482 /* Calling this from an exception handler is prohibited */
1483 if (OS_GetCurrentThread() == NULL)
1484 {
1485 SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1486 return SNDEX_RESULT_ILLEGAL_STATE;
1487 }
1488
1489 /* Skip CheckState if the SNDEXi_PreProcessForShutterSound function has already been called. */
1490 if (sndexState != SNDEX_STATE_PLAY_SHUTTER)
1491 {
1492 /* Confirm status */
1493 result = CheckState();
1494 if (result != SNDEX_RESULT_SUCCESS)
1495 {
1496 return result;
1497 }
1498 }
1499 else if (sndexState == SNDEX_STATE_POST_PROC_SHUTTER)
1500 {
1501 return SNDEX_RESULT_EXCLUSIVE;
1502 }
1503
1504 /* Initialize the message queue used for synchronization */
1505 OS_InitMessageQueue(&msgQ, msg, 1);
1506
1507
1508 /* Register process */
1509 SetSndexWork(SyncCallback, (void*)(&msgQ), NULL, SNDEX_PXI_COMMAND_PRE_PROC_SHUTTER);
1510
1511 /* Issue command to ARM7 */
1512 if (FALSE == SendCommand(sndexWork.command, 0))
1513 {
1514 return SNDEX_RESULT_PXI_SEND_ERROR;
1515 }
1516
1517 /* Wait for reply */
1518 (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1519
1520 return result;
1521 }
1522
1523 /*---------------------------------------------------------------------------*
1524 Name: SNDEXi_PostProcessCallbackForShutterSound
1525
1526 Description: Executes postprocessing for shutter sound playback.
1527 This is executed asynchronously because it is executed inside an interrupt.
1528
1529 Arguments: callback: Callback function called when the postprocessing completes
1530 arg: Parameter passed to the callback function
1531
1532 Returns: Returns SNDEX_RESULT_SUCCESS if successful.
1533 *---------------------------------------------------------------------------*/
1534 SNDEXResult
SNDEXi_PostProcessForShutterSound(SNDEXCallback callback,void * arg)1535 SNDEXi_PostProcessForShutterSound (SNDEXCallback callback, void* arg)
1536 {
1537 /* Check CODEC operating mode */
1538 // When this function is called, it is presumed to be after execution of SNDEXi_PreProcessCallbackForShutterSound
1539 if (OSi_IsCodecTwlMode() == FALSE || sndexState != SNDEX_STATE_PLAY_SHUTTER)
1540 {
1541 return SNDEX_RESULT_ILLEGAL_STATE;
1542 }
1543
1544 /* Transition the state to postprocessing (maximum priority) */
1545 sndexState = SNDEX_STATE_POST_PROC_SHUTTER;
1546
1547 /* Register asynchronous process */
1548 SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_POST_PROC_SHUTTER);
1549
1550 /* Issue command to ARM7 */
1551 if (FALSE == SendCommand(sndexWork.command, 0))
1552 {
1553 return SNDEX_RESULT_PXI_SEND_ERROR;
1554 }
1555
1556 return SNDEX_RESULT_SUCCESS;
1557 }
1558
1559 /*---------------------------------------------------------------------------*
1560 Name: CommonCallback
1561
1562 Description: PXI FIFO reception callback function for processes related to the extended sound features.
1563
1564 Arguments: tag: PXI message type
1565 data: Message content from ARM7
1566 err: PXI transfer error flag
1567
1568 Returns: None.
1569 *---------------------------------------------------------------------------*/
1570 static void
CommonCallback(PXIFifoTag tag,u32 data,BOOL err)1571 CommonCallback (PXIFifoTag tag, u32 data, BOOL err)
1572 {
1573 u8 command = (u8)((data & SNDEX_PXI_COMMAND_MASK) >> SNDEX_PXI_COMMAND_SHIFT);
1574 u8 result = (u8)((data & SNDEX_PXI_RESULT_MASK) >> SNDEX_PXI_RESULT_SHIFT);
1575 u8 param = (u8)((data & SNDEX_PXI_PARAMETER_MASK) >> SNDEX_PXI_PARAMETER_SHIFT);
1576
1577 /* If the command received from ARM7 is a notification that the system volume switch was pressed, try locking */
1578 if (command == SNDEX_PXI_COMMAND_PRESS_VOLSWITCH)
1579 {
1580 SNDEXResult result = CheckState();
1581 if (result != SNDEX_RESULT_SUCCESS)
1582 {
1583 return;
1584 }
1585 // Set the sndexWork structure
1586 SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_PRESS_VOLSWITCH);
1587 }
1588
1589 /* Confirm status */
1590 if ((tag != PXI_FIFO_TAG_SNDEX) || (err == TRUE)
1591 || (sndexState != SNDEX_STATE_LOCKED && sndexState != SNDEX_STATE_PLAY_SHUTTER && sndexState != SNDEX_STATE_POST_PROC_SHUTTER)
1592 || (sndexWork.command != command))
1593 {
1594 /* Logically, execution will never be able to pass through here, but output a warning just in case */
1595 OS_TWarning("SNDEX: Library state is inconsistent.\n");
1596 ReplyCallback(SNDEX_RESULT_FATAL_ERROR);
1597 return;
1598 }
1599
1600 /* Parse the process results */
1601 switch (result)
1602 {
1603 case SNDEX_PXI_RESULT_SUCCESS:
1604 /* Perform completion processing in accordance with the command */
1605 switch (command)
1606 {
1607 case SNDEX_PXI_COMMAND_GET_SMIX_MUTE:
1608 if (sndexWork.dest != NULL)
1609 {
1610 *((SNDEXMute*)sndexWork.dest) = (SNDEXMute)param;
1611 }
1612 break;
1613 case SNDEX_PXI_COMMAND_GET_SMIX_FREQ:
1614 if (sndexWork.dest != NULL)
1615 {
1616 *((SNDEXFrequency*)sndexWork.dest) = (SNDEXFrequency)param;
1617 }
1618 break;
1619 case SNDEX_PXI_COMMAND_GET_SMIX_DSP:
1620 case SNDEX_PXI_COMMAND_GET_VOLUME:
1621 if (sndexWork.dest != NULL)
1622 {
1623 *((u8*)sndexWork.dest) = param;
1624 }
1625 break;
1626 case SNDEX_PXI_COMMAND_GET_SND_DEVICE:
1627 if (sndexWork.dest != NULL)
1628 {
1629 *((SNDEXDevice*)sndexWork.dest) = (SNDEXDevice)param;
1630 }
1631 break;
1632 case SNDEX_PXI_COMMAND_PRESS_VOLSWITCH:
1633 /* Notification from ARM7 that the volume button was pressed */
1634 if (SNDEXi_VolumeSwitchCallbackInfo.callback != NULL)
1635 {
1636 (SNDEXi_VolumeSwitchCallbackInfo.callback)((SNDEXResult)result, SNDEXi_VolumeSwitchCallbackInfo.cbArg);
1637 }
1638 break;
1639 case SNDEX_PXI_COMMAND_HP_CONNECT:
1640 if (sndexWork.dest != NULL)
1641 {
1642 *((SNDEXHeadphone*)sndexWork.dest) = (SNDEXHeadphone)param;
1643 }
1644 break;
1645 }
1646 ReplyCallback(SNDEX_RESULT_SUCCESS);
1647 break;
1648 case SNDEX_PXI_RESULT_INVALID_PARAM:
1649 ReplyCallback(SNDEX_RESULT_INVALID_PARAM);
1650 break;
1651 case SNDEX_PXI_RESULT_EXCLUSIVE:
1652 ReplyCallback(SNDEX_RESULT_EXCLUSIVE);
1653 break;
1654 case SNDEX_PXI_RESULT_ILLEGAL_STATE:
1655 ReplyCallback(SNDEX_RESULT_ILLEGAL_STATE);
1656 break;
1657 case SNDEX_PXI_RESULT_DEVICE_ERROR:
1658 if (command == SNDEX_PXI_COMMAND_GET_VOLUME)
1659 {
1660 if (sndexWork.dest != NULL)
1661 {
1662 *((u8*)sndexWork.dest) = SNDEX_VOLUME_MIN;
1663 }
1664 }
1665 ReplyCallback(SNDEX_RESULT_DEVICE_ERROR);
1666 break;
1667 case SNDEX_PXI_RESULT_INVALID_COMMAND:
1668 default:
1669 ReplyCallback(SNDEX_RESULT_FATAL_ERROR);
1670 break;
1671 }
1672 }
1673
1674 /*---------------------------------------------------------------------------*
1675 Name: SyncCallback
1676
1677 Description: Shared callback function for synchronous function control.
1678
1679 Arguments: result: Result of asynchronous processing
1680 arg: Message being blocked by the synchronous function while it waits for reception.
1681 Pointer to queue control structure.
1682
1683 Returns: None.
1684 *---------------------------------------------------------------------------*/
1685 static void
SyncCallback(SNDEXResult result,void * arg)1686 SyncCallback (SNDEXResult result, void* arg)
1687 {
1688 SDK_NULL_ASSERT(arg);
1689
1690 if (FALSE == OS_SendMessage((OSMessageQueue*)arg, (OSMessage)result, OS_MESSAGE_NOBLOCK))
1691 {
1692 /* Logically, execution will never be able to pass through here, but output a warning just in case */
1693 OS_TWarning("SNDEX: Temporary message queue is full.\n");
1694 }
1695 }
1696
1697 /*---------------------------------------------------------------------------*
1698 Name: SendCommand
1699
1700 Description: Issues an extended sound feature operation command to ARM7 via PXI.
1701
1702 Arguments: command: Command type
1703 param: Parameter associated with the command
1704
1705 Returns: BOOL: Returns TRUE if PXI transmission was successful.
1706 *---------------------------------------------------------------------------*/
1707 static BOOL
SendCommand(u8 command,u8 param)1708 SendCommand (u8 command, u8 param)
1709 {
1710 OSIntrMode e = OS_DisableInterrupts();
1711 u32 packet = (u32)(((command << SNDEX_PXI_COMMAND_SHIFT) & SNDEX_PXI_COMMAND_MASK)
1712 | ((param << SNDEX_PXI_PARAMETER_SHIFT) & SNDEX_PXI_PARAMETER_MASK));
1713
1714 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_SNDEX, packet, 0))
1715 {
1716 /* Cancel mutex if send failed */
1717 sndexState = SNDEX_STATE_INITIALIZED;
1718 (void)OS_RestoreInterrupts(e);
1719 SNDEXi_Warning("SNDEX: Failed to send PXI command.\n");
1720 return FALSE;
1721 }
1722
1723 (void)OS_RestoreInterrupts(e);
1724 return TRUE;
1725 }
1726
1727 /*---------------------------------------------------------------------------*
1728 Name: SendCommand
1729
1730 Description: Issues an extended sound feature operation command to ARM7 via PXI.
1731
1732 Arguments: command: Command type
1733 param: Parameter associated with the command (16 bits because of the IirFilter parameter)
1734
1735 Returns: BOOL: Returns TRUE if PXI transmission was successful.
1736 *---------------------------------------------------------------------------*/
1737 static BOOL
SendCommandEx(u8 command,u16 param)1738 SendCommandEx (u8 command, u16 param)
1739 {
1740 OSIntrMode e = OS_DisableInterrupts();
1741 u32 packet = (u32)(((command << SNDEX_PXI_COMMAND_SHIFT) & SNDEX_PXI_COMMAND_MASK)
1742 | ((param << SNDEX_PXI_PARAMETER_SHIFT) & SNDEX_PXI_PARAMETER_MASK_IIR));
1743
1744 if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_SNDEX, packet, 0))
1745 {
1746 /* Cancel mutex if send failed */
1747 sndexState = SNDEX_STATE_INITIALIZED;
1748 (void)OS_RestoreInterrupts(e);
1749 SNDEXi_Warning("SNDEX: Failed to send PXI command.\n");
1750 return FALSE;
1751 }
1752 if( command == SNDEX_PXI_COMMAND_SET_IIRFILTER )
1753 {
1754 isLockSpi = TRUE;
1755 }
1756
1757 (void)OS_RestoreInterrupts(e);
1758 return TRUE;
1759 }
1760
1761 /*---------------------------------------------------------------------------*
1762 Name: CheckState
1763
1764 Description: Checks whether the internal state is one where an asynchronous process can start, and if so, locks the SNDEX library.
1765
1766 Arguments: None.
1767
1768 Returns: None.
1769 *---------------------------------------------------------------------------
1770 */
1771 static SNDEXResult
CheckState(void)1772 CheckState (void)
1773 {
1774 OSIntrMode e = OS_DisableInterrupts();
1775
1776 /* Check internal state */
1777 switch (sndexState)
1778 {
1779 case SNDEX_STATE_BEFORE_INIT:
1780 case SNDEX_STATE_INITIALIZING:
1781 (void)OS_RestoreInterrupts(e);
1782 SNDEXi_Warning("SNDEX: Library is not initialized yet.\n");
1783 return SNDEX_RESULT_BEFORE_INIT;
1784 case SNDEX_STATE_LOCKED:
1785 case SNDEX_STATE_PLAY_SHUTTER:
1786 case SNDEX_STATE_POST_PROC_SHUTTER:
1787 (void)OS_RestoreInterrupts(e);
1788 SNDEXi_Warning("SNDEX: Another request is in progress.\n");
1789 return SNDEX_RESULT_EXCLUSIVE;
1790 }
1791
1792 /* Transition to state where exclusion control is in effect */
1793 sndexState = SNDEX_STATE_LOCKED;
1794 (void)OS_RestoreInterrupts(e);
1795 return SNDEX_RESULT_SUCCESS;
1796 }
1797
1798 /*---------------------------------------------------------------------------*
1799 Name: ReplyCallback
1800
1801 Description: Sends notification of the completion of asynchronous processing. Updates the internal state and also unlocks the exclusion state.
1802
1803 Arguments: result: Asynchronous processing result to notify to the callback function
1804
1805 Returns: None.
1806 *---------------------------------------------------------------------------
1807 */
1808 static void
ReplyCallback(SNDEXResult result)1809 ReplyCallback (SNDEXResult result)
1810 {
1811 OSIntrMode e = OS_DisableInterrupts();
1812 SNDEXCallback callback = sndexWork.callback;
1813 void* cbArg = sndexWork.cbArg;
1814 u8 command = sndexWork.command;
1815
1816 // Assume that the SPI_Lock was ended by SetIirFilterAsync, and lower the flag
1817 if (sndexWork.command == SNDEX_PXI_COMMAND_SET_IIRFILTER)
1818 {
1819 isLockSpi = FALSE;
1820 isIirFilterSetting = FALSE;
1821 }
1822
1823 /* Reset state */
1824 SetSndexWork(NULL, NULL, NULL, 0);
1825 // If currently preprocessing the shutter sound playback, do not unlock until postprocessing begins
1826 if (command == SNDEX_PXI_COMMAND_PRE_PROC_SHUTTER)
1827 {
1828 // Anything other than the SNDEXi_PostProcessForShutterSound function, which performs shutter sound playback postprocessing, is considered locked and is excluded.
1829 //
1830 sndexState = SNDEX_STATE_PLAY_SHUTTER;
1831 }
1832 else
1833 {
1834 sndexState = SNDEX_STATE_INITIALIZED;
1835 }
1836 (void)OS_RestoreInterrupts(e);
1837
1838 /* Call the registered callback function */
1839 if (callback != NULL)
1840 {
1841 callback(result, cbArg);
1842 }
1843 }
1844
1845 /*---------------------------------------------------------------------------*
1846 Name: SetSndexWork
1847
1848 Description: Sets parameters for sndexWork.
1849
1850 Arguments: cb: Pointer to the callback function
1851 cbarg: Argument to pass to 'cb'
1852 dst: Pointer to a variable to store the command's processing results
1853 command: Command to send to ARM7
1854
1855 Returns: None.
1856 *---------------------------------------------------------------------------*/
1857 static void
SetSndexWork(SNDEXCallback cb,void * cbarg,void * dst,u8 command)1858 SetSndexWork (SNDEXCallback cb, void* cbarg, void* dst, u8 command)
1859 {
1860 sndexWork.callback = cb;
1861 sndexWork.cbArg = cbarg;
1862 sndexWork.dest = dst;
1863 sndexWork.command = command;
1864 }
1865
1866 /*---------------------------------------------------------------------------*
1867 Name: SndexSleepAndExitCallback
1868
1869 Description: This callback function is invoked at hardware reset, shutdown, or transition to Sleep Mode.
1870
1871 Arguments: arg
1872
1873 Returns: None.
1874 *---------------------------------------------------------------------------
1875 */
1876 static void
SndexSleepAndExitCallback(void * arg)1877 SndexSleepAndExitCallback (void *arg)
1878 {
1879 #pragma unused( arg )
1880 // Always wait for IIR filter processing to finish first, because while it is running, other SNDEX functions may be exclusively locked in the SNDEX library.
1881 //
1882 WaitIirFilterSetting();
1883
1884 ResetTempVolume();
1885 }
1886
1887 /*---------------------------------------------------------------------------*
1888 Name: WaitIirFilterSetting
1889
1890 Description: Waits for SNDEX_SetIirFilter[Async] to end.
1891
1892 Arguments: None.
1893
1894 Returns: None.
1895 *---------------------------------------------------------------------------*/
1896 static void
WaitIirFilterSetting(void)1897 WaitIirFilterSetting (void)
1898 {
1899 // Continue waiting until the SPI_Lock in SNDEX_SetIirFilter[Async] ends
1900 while (isLockSpi)
1901 {
1902 OS_SpinWait(67 * 1000); //Approximately 1 ms
1903 PXIi_HandlerRecvFifoNotEmpty();
1904 }
1905 }
1906
1907 static void
WaitResetSoundCallback(SNDEXResult result,void * arg)1908 WaitResetSoundCallback(SNDEXResult result, void* arg)
1909 {
1910 static u32 i = 0; // Retry up to 5 times
1911 #pragma unused(arg)
1912 if (result != SNDEX_RESULT_SUCCESS && i < 5)
1913 {
1914 (void)SNDEXi_SetVolumeExAsync(storeVolume, WaitResetSoundCallback, NULL);
1915 i++;
1916 return;
1917 }
1918 isStoreVolume = FALSE;
1919 }
1920
1921 /*---------------------------------------------------------------------------*
1922 Name: ResetTempVolume
1923
1924 Description: Reverts to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume.
1925
1926 Arguments: None.
1927
1928 Returns: None.
1929 *---------------------------------------------------------------------------*/
1930 static void
ResetTempVolume(void)1931 ResetTempVolume (void)
1932 {
1933 if (isStoreVolume)
1934 {
1935 static i = 0; // Retry up to 5 times
1936 // Revert to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume
1937 // Repeat until the asynchronous function runs successfully
1938 // The callback will handle retries having to do with success or failure of the volume change
1939 while( SNDEX_RESULT_SUCCESS != SNDEXi_SetVolumeExAsync(storeVolume, WaitResetSoundCallback, NULL) && i < 5)
1940 {
1941 i++;
1942 }
1943 while (isStoreVolume)
1944 {
1945 OS_SpinWait(67 * 1000); //Approximately 1 ms
1946 PXIi_HandlerRecvFifoNotEmpty();
1947 }
1948 }
1949 }
1950
1951