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:: 2009-06-29#$
14   $Rev: 10832 $
15   $Author: nishimoto_takashi $
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;              // This indicates 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                 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
163 
164 
165   Arguments:    mute: Buffer used to get the mute status
166                 callback: Callback function that notifies of the results when the asynchronous process is completed
167 
168                 arg: Parameter passed to the callback function
169 
170   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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                 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
240 
241 
242   Arguments:    freq: Buffer used to get the frequency information
243                 callback: Callback function that notifies of the results when the asynchronous process is completed
244 
245                 arg: Parameter passed to the callback function
246 
247   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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                 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
318 
319 
320   Arguments:    rate: Buffer used to get the mix rate information
321                 callback: Callback function that notifies of the results when the asynchronous process is completed
322 
323                 arg: Parameter passed to the callback function
324 
325   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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                 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
396 
397 
398   Arguments:    volume: Buffer used to get the volume information
399                 callback: Callback function that notifies of the results when the asynchronous process is completed
400 
401                 arg: Parameter passed to the callback function
402                 eightlv: Gets the volume as one of eight levels
403                 keep: Gets the amount of volume reserved for changes in volume. If there is no amount reserved, gets the current value
404 
405   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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                 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
478 
479 
480   Arguments:    volume: Buffer used to get the volume information
481                 callback: Callback function that notifies of the results when the asynchronous process is completed
482 
483                 arg: Parameter passed to the callback function
484 
485   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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                 If this is the asynchronous function, the writing of results to the results buffer is asynchronous compared to the function call, so the buffer should not be used for other purposes until the asynchronous process completes.
527 
528 
529   Arguments:    volume: Buffer used to get the volume information
530                [callback: Callback function that notifies the results when the asynchronous processing is completed]
531                [arg: Parameter passed to the callback function]
532 
533   Returns:      SNDEXResult: Returns processing results.
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                 Because the writing of results to the results buffer is asynchronous compared to the function call, the buffer should not be used for other purposes until the asynchronous process completes.
562 
563 
564   Arguments:    device: Buffer used to get the output device information
565                 callback: Callback function that notifies of the results when the asynchronous process is completed
566 
567                 arg: Parameter passed to the callback function
568 
569   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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 process is completed
641 
642                 arg: Parameter passed to the callback function
643 
644   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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 process is completed
721 
722                 arg: Parameter passed to the callback function
723 
724   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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 process is completed
808 
809                 arg: Parameter passed to the callback function
810 
811   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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 process is completed
896 
897                 arg: Parameter passed to the callback function
898                 eightlv: Sets the volume as one of eight levels
899 
900   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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 process is completed
978 
979                 arg: Parameter passed to the callback function
980 
981   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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 process is completed
1024 
1025                 arg: Parameter passed to the callback function
1026 
1027   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
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!!: Because it is not possible to pass all parameters to ARM7 with one PXI transmission, this uses multiple back-to-back transfers. However, if it simply makes several transfers back-to-back, sometimes the previously sent parameters will not yet be processed when the next set arrives. For this reason, this function also waits before each PXI transfer until the previous transfer's parameters are processed.
1109 
1110 
1111 
1112 
1113   Arguments:    target:
1114                 pParam:
1115 
1116   Returns:      None.
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     // Return an error if already processing SetIirFilterAsync
1122     if (isIirFilterSetting)
1123     {
1124         return SNDEX_RESULT_EXCLUSIVE;
1125     }
1126     isIirFilterSetting = TRUE;
1127 
1128     /* Check CODEC operating mode */
1129     if (OSi_IsCodecTwlMode() == FALSE)
1130     {
1131         SNDEXi_Warning("%s: Illegal state\n", __FUNCTION__);
1132         isIirFilterSetting = FALSE;
1133         return SNDEX_RESULT_ILLEGAL_STATE;
1134     }
1135 
1136     /* Confirm status */
1137     {
1138         SNDEXResult result  =   CheckState();
1139         if (result != SNDEX_RESULT_SUCCESS)
1140         {
1141             isIirFilterSetting = FALSE;
1142             return result;
1143         }
1144     }
1145 
1146   /* Target */
1147     /* Register asynchronous process */
1148     SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_TARGET);
1149     /* Issue command to ARM7 */
1150     if (FALSE == SendCommandEx(sndexWork.command, (u16)target))
1151     {
1152         isIirFilterSetting = FALSE;
1153         return SNDEX_RESULT_PXI_SEND_ERROR;
1154     }
1155     // Wait for the callback by idling in an empty loop so that there is time for the CheckState function's Warning suppression
1156     OS_SpinWait(67 * 1000); //Approximately 1 ms
1157 
1158     // Wait until the previous PXI transfer's processing ends
1159     while ( CheckState() != SNDEX_RESULT_SUCCESS )
1160     {
1161         OS_SpinWait(67 * 1000); //Approximately 1 ms
1162     }
1163 
1164   /* Filter parameter */
1165     // n0
1166     SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N0);
1167     /* Issue command to ARM7 */
1168     if (FALSE == SendCommandEx(sndexWork.command, pParam->n0))
1169     {
1170         isIirFilterSetting = FALSE;
1171         return SNDEX_RESULT_PXI_SEND_ERROR;
1172     }
1173     OS_SpinWait(67 * 1000); //Approximately 1 ms
1174 
1175     // Wait until the previous PXI transfer's processing ends
1176     while ( CheckState() != SNDEX_RESULT_SUCCESS )
1177     {
1178         OS_SpinWait(67 * 1000); //Approximately 1 ms
1179     }
1180 
1181     // n1
1182     SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N1);
1183     /* Issue command to ARM7 */
1184     if (FALSE == SendCommandEx(sndexWork.command, pParam->n1))
1185     {
1186         isIirFilterSetting = FALSE;
1187         return SNDEX_RESULT_PXI_SEND_ERROR;
1188     }
1189     OS_SpinWait(67 * 1000); //Approximately 1 ms
1190 
1191     // Wait until the previous PXI transfer's processing ends
1192     while ( CheckState() != SNDEX_RESULT_SUCCESS )
1193     {
1194         OS_SpinWait(67 * 1000); //Approximately 1 ms
1195     }
1196 
1197     // n2
1198     SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_N2);
1199     /* Issue command to ARM7 */
1200     if (FALSE == SendCommandEx(sndexWork.command, pParam->n2))
1201     {
1202         isIirFilterSetting = FALSE;
1203         return SNDEX_RESULT_PXI_SEND_ERROR;
1204     }
1205     OS_SpinWait(67 * 1000); //Approximately 1 ms
1206 
1207     // Wait until the previous PXI transfer's processing ends
1208     while ( CheckState() != SNDEX_RESULT_SUCCESS )
1209     {
1210         OS_SpinWait(67 * 1000); //Approximately 1 ms
1211     }
1212 
1213     // d1
1214     SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_D1);
1215     /* Issue command to ARM7 */
1216     if (FALSE == SendCommandEx(sndexWork.command, pParam->d1))
1217     {
1218         isIirFilterSetting = FALSE;
1219         return SNDEX_RESULT_PXI_SEND_ERROR;
1220     }
1221     OS_SpinWait(67 * 1000); //Approximately 1 ms
1222 
1223     // Wait until the previous PXI transfer's processing ends
1224     while ( CheckState() != SNDEX_RESULT_SUCCESS )
1225     {
1226         OS_SpinWait(67 * 1000); //Approximately 1 ms
1227     }
1228 
1229     // d2
1230     SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER_PARAM_D2);
1231     /* Issue command to ARM7 */
1232     if (FALSE == SendCommandEx(sndexWork.command, pParam->d2))
1233     {
1234         isIirFilterSetting = FALSE;
1235         return SNDEX_RESULT_PXI_SEND_ERROR;
1236     }
1237     OS_SpinWait(67 * 1000); //Approximately 1 ms
1238 
1239     // Wait until the previous PXI transfer's processing ends
1240     while ( CheckState() != SNDEX_RESULT_SUCCESS )
1241     {
1242         OS_SpinWait(67 * 1000); //Approximately 1 ms
1243     }
1244 
1245   /* Set the target and the filter parameters */
1246     SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_SET_IIRFILTER);
1247     /* Issue command to ARM7 */
1248     if (FALSE == SendCommandEx(sndexWork.command, 0))
1249     {
1250         isIirFilterSetting = FALSE;
1251         return SNDEX_RESULT_PXI_SEND_ERROR;
1252     }
1253 
1254     return SNDEX_RESULT_SUCCESS;
1255 }
1256 
1257 /*---------------------------------------------------------------------------*
1258   Name:         SNDEXi_SetIirFilter
1259 
1260   Description:  Sets the IIR filter (Biquad) parameters.
1261 
1262   Arguments:    target:
1263                 pParam:
1264 
1265   Returns:      None.
1266  *---------------------------------------------------------------------------*/
1267 SNDEXResult
SNDEXi_SetIirFilter(SNDEXIirFilterTarget target,const SNDEXIirFilterParam * pParam)1268 SNDEXi_SetIirFilter(SNDEXIirFilterTarget target, const SNDEXIirFilterParam* pParam)
1269 {
1270     SNDEXResult     result;
1271     OSMessageQueue  msgQ;
1272     OSMessage       msg[1];
1273 
1274     /* Calling this from an exception handler is prohibited */
1275     if (OS_GetCurrentThread() == NULL)
1276     {
1277         SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1278         return SNDEX_RESULT_ILLEGAL_STATE;
1279     }
1280 
1281     /* Initialize the message queue used for synchronization */
1282     OS_InitMessageQueue(&msgQ, msg, 1);
1283 
1284     result = SNDEXi_SetIirFilterAsync(target, pParam, SyncCallback, (void*)(&msgQ));
1285     if (result == SNDEX_RESULT_SUCCESS)
1286     {
1287         (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1288     }
1289 
1290     // Assume that the SPI_Lock was ended by SetIirFilter, and lower the flag
1291     isLockSpi = FALSE;
1292 
1293     isIirFilterSetting = FALSE;
1294 
1295     return result;
1296 }
1297 
1298 /*---------------------------------------------------------------------------*
1299   Name:         SNDEX_IsConnectedHeadphoneAsync
1300 
1301   Description:  Gets whether headphones are connected.
1302 
1303   Arguments:    hp: Buffer used to get headphone connection status
1304                 callback: Callback function that notifies of the results when the asynchronous process is completed
1305 
1306                 arg: Parameter passed to the callback function
1307 
1308   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
1309 
1310 
1311  *---------------------------------------------------------------------------*/
1312 SNDEXResult
SNDEXi_IsConnectedHeadphoneAsync(SNDEXHeadphone * hp,SNDEXCallback callback,void * arg)1313 SNDEXi_IsConnectedHeadphoneAsync(SNDEXHeadphone *hp, SNDEXCallback callback, void* arg)
1314 {
1315     /* Confirm status */
1316     {
1317         SNDEXResult result  =   CheckState();
1318         if (result != SNDEX_RESULT_SUCCESS)
1319         {
1320             return result;
1321         }
1322     }
1323 
1324     /* Register asynchronous process */
1325     SetSndexWork(callback, arg, (void*)hp, SNDEX_PXI_COMMAND_HP_CONNECT);
1326 
1327     /* Issue command to ARM7 */
1328     if (FALSE == SendCommand(sndexWork.command, 0))
1329     {
1330         return SNDEX_RESULT_PXI_SEND_ERROR;
1331     }
1332     return SNDEX_RESULT_SUCCESS;
1333 }
1334 
1335 /*---------------------------------------------------------------------------*
1336   Name:         SNDEX_IsConnectedHeadphone
1337 
1338   Description:  Gets whether headphones are connected.
1339 
1340   Arguments:    hp: Buffer used to get headphone connection status
1341 
1342   Returns:      SNDEXResult: Returns processing results. When returning SNDEX_RESULT_SUCCESS, the actual processing results are notified to the function registered to the callback after the asynchronous process is complete.
1343 
1344 
1345  *---------------------------------------------------------------------------*/
1346 SNDEXResult
SNDEXi_IsConnectedHeadphone(SNDEXHeadphone * hp)1347 SNDEXi_IsConnectedHeadphone(SNDEXHeadphone *hp)
1348 {
1349     SNDEXResult     result;
1350     OSMessageQueue  msgQ;
1351     OSMessage       msg[1];
1352 
1353     /* Calling this from an exception handler is prohibited */
1354     if (OS_GetCurrentThread() == NULL)
1355     {
1356         SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1357         return SNDEX_RESULT_ILLEGAL_STATE;
1358     }
1359 
1360     /* Initialize the message queue used for synchronization */
1361     OS_InitMessageQueue(&msgQ, msg, 1);
1362 
1363     /* Execute the asynchronous function and idle the callback */
1364     result  =   SNDEXi_IsConnectedHeadphoneAsync(hp, SyncCallback, (void*)(&msgQ));
1365     if (result == SNDEX_RESULT_SUCCESS)
1366     {
1367         (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1368     }
1369     return result;
1370 }
1371 
1372 /*---------------------------------------------------------------------------*
1373   Name:         SNDEXi_SetVolumeSwitchCallback
1374 
1375   Description:  Sets the callback function that is called when the volume button is pressed.
1376 
1377   Arguments:    callback: Callback function called when the volume button is pressed
1378                 arg: Parameter passed to the callback function
1379 
1380   Returns:      None.
1381  *---------------------------------------------------------------------------*/
SNDEXi_SetVolumeSwitchCallback(SNDEXCallback callback,void * arg)1382 void SNDEXi_SetVolumeSwitchCallback(SNDEXCallback callback, void* arg)
1383 {
1384     SNDEXi_VolumeSwitchCallbackInfo.callback = callback;
1385     SNDEXi_VolumeSwitchCallbackInfo.cbArg = arg;
1386 }
1387 
1388 /*---------------------------------------------------------------------------*
1389   Name:         SNDEXi_SetIgnoreHWVolume
1390 
1391   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.
1392 
1393 
1394                 This function saves the volume before changing it.
1395 
1396   Arguments:    volume: Value to change the volume to
1397 
1398   Returns:      SNDEXResult: Returns processing results. This is the result of an SNDEX function called internally.
1399  *---------------------------------------------------------------------------*/
SNDEXi_SetIgnoreHWVolume(u8 volume,BOOL eightlv)1400 SNDEXResult SNDEXi_SetIgnoreHWVolume(u8 volume, BOOL eightlv)
1401 {
1402     SNDEXResult result;
1403     result = SNDEXi_GetVolumeEx(&storeVolume);
1404     if (result != SNDEX_RESULT_SUCCESS)
1405     {
1406         return result;
1407     }
1408 
1409     // Change the volume to the specified value
1410     result = eightlv ? SNDEX_SetVolume(volume) : SNDEXi_SetVolumeEx(volume);
1411     if (result != SNDEX_RESULT_SUCCESS)
1412     {
1413         return result;
1414     }
1415 
1416     isStoreVolume = TRUE;
1417     return result;      // SNDEX_RESULT_SUCCESS
1418 }
1419 
1420 /*---------------------------------------------------------------------------*
1421   Name:         SNDEXi_ResetIgnoreHWVolume
1422 
1423   Description:  Restores the volume to its value before changed by SNDEX_SetIgnoreHWVolume.
1424 
1425   Arguments:    None.
1426 
1427   Returns:      SNDEXResult: Returns processing results.
1428  *---------------------------------------------------------------------------*/
SNDEXi_ResetIgnoreHWVolume(void)1429 SNDEXResult SNDEXi_ResetIgnoreHWVolume(void)
1430 {
1431     SNDEXResult result;
1432     if ((result = SNDEXi_SetVolumeEx(storeVolume)) != SNDEX_RESULT_SUCCESS)
1433     {
1434         return result;
1435     }
1436 
1437     isStoreVolume = FALSE;
1438     return result;          // SNDEX_RESULT_SUCCESS
1439 }
1440 
1441 /*---------------------------------------------------------------------------*
1442   Name:         SNDEXi_PreProcessForShutterSound
1443 
1444   Description:  Performs all the preprocessing necessary for shutter sound playback.
1445                 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
1446 
1447   Arguments:    None.
1448 
1449   Returns:      Returns SNDEX_RESULT_SUCCESS if successful.
1450  *---------------------------------------------------------------------------*/
1451 SNDEXResult
SNDEXi_PreProcessForShutterSound(void)1452 SNDEXi_PreProcessForShutterSound  (void)
1453 {
1454     SNDEXResult     result;
1455     OSMessageQueue  msgQ;
1456     OSMessage       msg[1];
1457 
1458     /* Check CODEC operating mode */
1459     if (OSi_IsCodecTwlMode() == FALSE)
1460     {
1461         return SNDEX_RESULT_ILLEGAL_STATE;
1462     }
1463 
1464     /* Calling this from an exception handler is prohibited */
1465     if (OS_GetCurrentThread() == NULL)
1466     {
1467         SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1468         return SNDEX_RESULT_ILLEGAL_STATE;
1469     }
1470 
1471     /* Skip CheckState if the SNDEXi_PreProcessForShutterSound function has already been called. */
1472     if (sndexState != SNDEX_STATE_PLAY_SHUTTER)
1473     {
1474         /* Confirm status */
1475         result  =   CheckState();
1476         if (result != SNDEX_RESULT_SUCCESS)
1477         {
1478             return result;
1479         }
1480     }
1481     else if (sndexState == SNDEX_STATE_POST_PROC_SHUTTER)
1482     {
1483         return SNDEX_RESULT_EXCLUSIVE;
1484     }
1485 
1486     /* Initialize the message queue used for synchronization */
1487     OS_InitMessageQueue(&msgQ, msg, 1);
1488 
1489 
1490     /* Register process */
1491     SetSndexWork(SyncCallback, (void*)(&msgQ), NULL, SNDEX_PXI_COMMAND_PRE_PROC_SHUTTER);
1492 
1493     /* Issue command to ARM7 */
1494     if (FALSE == SendCommand(sndexWork.command, 0))
1495     {
1496         return SNDEX_RESULT_PXI_SEND_ERROR;
1497     }
1498 
1499     /* Wait for reply */
1500     (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1501 
1502     return result;
1503 }
1504 
1505 /*---------------------------------------------------------------------------*
1506   Name:         SNDEXi_PostProcessCallbackForShutterSound
1507 
1508   Description:  Executes postprocessing for shutter sound playback.
1509                 This is executed asynchronously because it is executed inside an interrupt.
1510 
1511   Arguments:    callback: Callback function called when the postprocessing completes
1512                 arg: Parameter passed to the callback function
1513 
1514   Returns:      Returns SNDEX_RESULT_SUCCESS if successful.
1515  *---------------------------------------------------------------------------*/
1516 SNDEXResult
SNDEXi_PostProcessForShutterSound(SNDEXCallback callback,void * arg)1517 SNDEXi_PostProcessForShutterSound (SNDEXCallback callback, void* arg)
1518 {
1519     /* Check CODEC operating mode */
1520     // When this function is called, it is presumed to be after execution of SNDEXi_PreProcessCallbackForShutterSound
1521     if (OSi_IsCodecTwlMode() == FALSE || sndexState != SNDEX_STATE_PLAY_SHUTTER)
1522     {
1523         return SNDEX_RESULT_ILLEGAL_STATE;
1524     }
1525 
1526     /* Transition the state to postprocessing (maximum priority) */
1527     sndexState = SNDEX_STATE_POST_PROC_SHUTTER;
1528 
1529     /* Register asynchronous process */
1530     SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_POST_PROC_SHUTTER);
1531 
1532     /* Issue command to ARM7 */
1533     if (FALSE == SendCommand(sndexWork.command, 0))
1534     {
1535         return SNDEX_RESULT_PXI_SEND_ERROR;
1536     }
1537 
1538     return SNDEX_RESULT_SUCCESS;
1539 }
1540 
1541 /*---------------------------------------------------------------------------*
1542   Name:         CommonCallback
1543 
1544   Description:  PXI FIFO reception callback function for processes related to the extended sound features.
1545 
1546   Arguments:    tag: PXI message type
1547                 data: Message content from ARM7
1548                 err: PXI transfer error flag
1549 
1550   Returns:      None.
1551  *---------------------------------------------------------------------------*/
1552 static void
CommonCallback(PXIFifoTag tag,u32 data,BOOL err)1553 CommonCallback (PXIFifoTag tag, u32 data, BOOL err)
1554 {
1555     u8      command =   (u8)((data & SNDEX_PXI_COMMAND_MASK) >> SNDEX_PXI_COMMAND_SHIFT);
1556     u8      result  =   (u8)((data & SNDEX_PXI_RESULT_MASK) >> SNDEX_PXI_RESULT_SHIFT);
1557     u8      param   =   (u8)((data & SNDEX_PXI_PARAMETER_MASK) >> SNDEX_PXI_PARAMETER_SHIFT);
1558 
1559     /* If the command received from ARM7 is a notification that the system volume switch was pressed, try locking */
1560     if (command == SNDEX_PXI_COMMAND_PRESS_VOLSWITCH)
1561     {
1562         SNDEXResult result = CheckState();
1563         if (result != SNDEX_RESULT_SUCCESS)
1564         {
1565             return;
1566         }
1567         // Set the sndexWork structure
1568         SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_PRESS_VOLSWITCH);
1569     }
1570 
1571     /* Confirm status */
1572     if ((tag != PXI_FIFO_TAG_SNDEX) || (err == TRUE)
1573             || (sndexState != SNDEX_STATE_LOCKED && sndexState != SNDEX_STATE_PLAY_SHUTTER && sndexState != SNDEX_STATE_POST_PROC_SHUTTER)
1574             || (sndexWork.command != command))
1575     {
1576         /* Logically, execution will never be able to pass through here, but output a warning just in case */
1577         OS_TWarning("SNDEX: Library state is inconsistent.\n");
1578         ReplyCallback(SNDEX_RESULT_FATAL_ERROR);
1579         return;
1580     }
1581 
1582     /* Parse the process results */
1583     switch (result)
1584     {
1585     case SNDEX_PXI_RESULT_SUCCESS:
1586         /* Perform completion processing in accordance with the command */
1587         switch (command)
1588         {
1589         case SNDEX_PXI_COMMAND_GET_SMIX_MUTE:
1590             if (sndexWork.dest != NULL)
1591             {
1592                 *((SNDEXMute*)sndexWork.dest)   = (SNDEXMute)param;
1593             }
1594             break;
1595         case SNDEX_PXI_COMMAND_GET_SMIX_FREQ:
1596             if (sndexWork.dest != NULL)
1597             {
1598                 *((SNDEXFrequency*)sndexWork.dest)  =   (SNDEXFrequency)param;
1599             }
1600             break;
1601         case SNDEX_PXI_COMMAND_GET_SMIX_DSP:
1602         case SNDEX_PXI_COMMAND_GET_VOLUME:
1603             if (sndexWork.dest != NULL)
1604             {
1605                 *((u8*)sndexWork.dest)  =   param;
1606             }
1607             break;
1608         case SNDEX_PXI_COMMAND_GET_SND_DEVICE:
1609             if (sndexWork.dest != NULL)
1610             {
1611                 *((SNDEXDevice*)sndexWork.dest) =   (SNDEXDevice)param;
1612             }
1613             break;
1614         case SNDEX_PXI_COMMAND_PRESS_VOLSWITCH:
1615             /* Notification from ARM7 that the volume button was pressed */
1616             if (SNDEXi_VolumeSwitchCallbackInfo.callback != NULL)
1617             {
1618                 (SNDEXi_VolumeSwitchCallbackInfo.callback)((SNDEXResult)result, SNDEXi_VolumeSwitchCallbackInfo.cbArg);
1619             }
1620             break;
1621         case SNDEX_PXI_COMMAND_HP_CONNECT:
1622             if (sndexWork.dest != NULL)
1623             {
1624                 *((SNDEXHeadphone*)sndexWork.dest) =   (SNDEXHeadphone)param;
1625             }
1626             break;
1627         }
1628         ReplyCallback(SNDEX_RESULT_SUCCESS);
1629         break;
1630     case SNDEX_PXI_RESULT_INVALID_PARAM:
1631         ReplyCallback(SNDEX_RESULT_INVALID_PARAM);
1632         break;
1633     case SNDEX_PXI_RESULT_EXCLUSIVE:
1634         ReplyCallback(SNDEX_RESULT_EXCLUSIVE);
1635         break;
1636     case SNDEX_PXI_RESULT_ILLEGAL_STATE:
1637         ReplyCallback(SNDEX_RESULT_ILLEGAL_STATE);
1638         break;
1639     case SNDEX_PXI_RESULT_DEVICE_ERROR:
1640         if (command == SNDEX_PXI_COMMAND_GET_VOLUME)
1641         {
1642             if (sndexWork.dest != NULL)
1643             {
1644                 *((u8*)sndexWork.dest)  =   SNDEX_VOLUME_MIN;
1645             }
1646         }
1647         ReplyCallback(SNDEX_RESULT_DEVICE_ERROR);
1648         break;
1649     case SNDEX_PXI_RESULT_INVALID_COMMAND:
1650     default:
1651         ReplyCallback(SNDEX_RESULT_FATAL_ERROR);
1652         break;
1653     }
1654 }
1655 
1656 /*---------------------------------------------------------------------------*
1657   Name:         SyncCallback
1658 
1659   Description:  Shared callback function for synchronous function control.
1660 
1661   Arguments:    result: Result of asynchronous processing
1662                 arg: Message being blocked by the synchronous function while it waits for reception.
1663                             Pointer to queue control structure.
1664 
1665   Returns:      None.
1666  *---------------------------------------------------------------------------*/
1667 static void
SyncCallback(SNDEXResult result,void * arg)1668 SyncCallback (SNDEXResult result, void* arg)
1669 {
1670     SDK_NULL_ASSERT(arg);
1671 
1672     if (FALSE == OS_SendMessage((OSMessageQueue*)arg, (OSMessage)result, OS_MESSAGE_NOBLOCK))
1673     {
1674         /* Logically, execution will never be able to pass through here, but output a warning just in case */
1675         OS_TWarning("SNDEX: Temporary message queue is full.\n");
1676     }
1677 }
1678 
1679 /*---------------------------------------------------------------------------*
1680   Name:         SendCommand
1681 
1682   Description:  Issues an extended sound feature operation command to ARM7 via PXI.
1683 
1684   Arguments:    command: Command type
1685                 param: Parameter associated with the command
1686 
1687   Returns:      BOOL: Returns TRUE if PXI transmission was successful.
1688  *---------------------------------------------------------------------------*/
1689 static BOOL
SendCommand(u8 command,u8 param)1690 SendCommand (u8 command, u8 param)
1691 {
1692     OSIntrMode  e   =   OS_DisableInterrupts();
1693     u32     packet  =   (u32)(((command << SNDEX_PXI_COMMAND_SHIFT) & SNDEX_PXI_COMMAND_MASK)
1694                         | ((param << SNDEX_PXI_PARAMETER_SHIFT) & SNDEX_PXI_PARAMETER_MASK));
1695 
1696     if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_SNDEX, packet, 0))
1697     {
1698         /* Lift exclusion controls if transmission failed */
1699         sndexState  =   SNDEX_STATE_INITIALIZED;
1700         (void)OS_RestoreInterrupts(e);
1701         SNDEXi_Warning("SNDEX: Failed to send PXI command.\n");
1702         return FALSE;
1703     }
1704 
1705     (void)OS_RestoreInterrupts(e);
1706     return TRUE;
1707 }
1708 
1709 /*---------------------------------------------------------------------------*
1710   Name:         SendCommand
1711 
1712   Description:  Issues an extended sound feature operation command to ARM7 via PXI.
1713 
1714   Arguments:    command: Command type
1715                 param: Parameter associated with the command (16 bits because of the IirFilter parameter)
1716 
1717   Returns:      BOOL: Returns TRUE if PXI transmission was successful.
1718  *---------------------------------------------------------------------------*/
1719 static BOOL
SendCommandEx(u8 command,u16 param)1720 SendCommandEx (u8 command, u16 param)
1721 {
1722     OSIntrMode  e   =   OS_DisableInterrupts();
1723     u32     packet  =   (u32)(((command << SNDEX_PXI_COMMAND_SHIFT) & SNDEX_PXI_COMMAND_MASK)
1724                         | ((param << SNDEX_PXI_PARAMETER_SHIFT) & SNDEX_PXI_PARAMETER_MASK_IIR));
1725 
1726     if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_SNDEX, packet, 0))
1727     {
1728         /* Lift exclusion controls if transmission failed */
1729         sndexState  =  SNDEX_STATE_INITIALIZED;
1730         (void)OS_RestoreInterrupts(e);
1731         SNDEXi_Warning("SNDEX: Failed to send PXI command.\n");
1732         return FALSE;
1733     }
1734     if( command == SNDEX_PXI_COMMAND_SET_IIRFILTER )
1735     {
1736         isLockSpi = TRUE;
1737     }
1738 
1739     (void)OS_RestoreInterrupts(e);
1740     return TRUE;
1741 }
1742 
1743 /*---------------------------------------------------------------------------*
1744   Name:         CheckState
1745 
1746   Description:  Checks whether the internal state is one where an asynchronous process can start, and if so, locks the SNDEX library.
1747 
1748 
1749   Arguments:    None.
1750 
1751   Returns:      None.
1752  *---------------------------------------------------------------------------*/
1753 static SNDEXResult
CheckState(void)1754 CheckState (void)
1755 {
1756     OSIntrMode  e   =   OS_DisableInterrupts();
1757 
1758     /* Check internal state */
1759     switch (sndexState)
1760     {
1761     case SNDEX_STATE_BEFORE_INIT:
1762     case SNDEX_STATE_INITIALIZING:
1763         (void)OS_RestoreInterrupts(e);
1764         SNDEXi_Warning("SNDEX: Library is not initialized yet.\n");
1765         return SNDEX_RESULT_BEFORE_INIT;
1766     case SNDEX_STATE_LOCKED:
1767     case SNDEX_STATE_PLAY_SHUTTER:
1768     case SNDEX_STATE_POST_PROC_SHUTTER:
1769         (void)OS_RestoreInterrupts(e);
1770         SNDEXi_Warning("SNDEX: Another request is in progress.\n");
1771         return SNDEX_RESULT_EXCLUSIVE;
1772     }
1773 
1774     /* Transition to state where exclusion control is in effect */
1775     sndexState  =   SNDEX_STATE_LOCKED;
1776     (void)OS_RestoreInterrupts(e);
1777     return SNDEX_RESULT_SUCCESS;
1778 }
1779 
1780 /*---------------------------------------------------------------------------*
1781   Name:         ReplyCallback
1782 
1783   Description:  Sends notification of the completion of asynchronous processing. Updates the internal sate and also lifts the exclusion state.
1784 
1785 
1786   Arguments:    result: Asynchronous processing result to notify to the callback function
1787 
1788   Returns:      None.
1789  *---------------------------------------------------------------------------*/
1790 static void
ReplyCallback(SNDEXResult result)1791 ReplyCallback (SNDEXResult result)
1792 {
1793     OSIntrMode      e           =   OS_DisableInterrupts();
1794     SNDEXCallback   callback    =   sndexWork.callback;
1795     void*           cbArg       =   sndexWork.cbArg;
1796     u8              command     =   sndexWork.command;
1797 
1798     // Assume that the SPI_Lock was ended by SetIirFilterAsync, and lower the flag
1799     if (sndexWork.command == SNDEX_PXI_COMMAND_SET_IIRFILTER)
1800     {
1801         isLockSpi = FALSE;
1802         isIirFilterSetting = FALSE;
1803     }
1804 
1805     /* Reset state */
1806     SetSndexWork(NULL, NULL, NULL, 0);
1807     // If currently preprocessing the shutter sound playback, do not unlock until postprocessing begins
1808     if (command == SNDEX_PXI_COMMAND_PRE_PROC_SHUTTER)
1809     {
1810         // Anything other than the SNDEXi_PostProcessForShutterSound function, which performs shutter sound playback postprocessing, is considered locked and is excluded.
1811         //
1812         sndexState          =   SNDEX_STATE_PLAY_SHUTTER;
1813     }
1814     else
1815     {
1816         sndexState          =   SNDEX_STATE_INITIALIZED;
1817     }
1818     (void)OS_RestoreInterrupts(e);
1819 
1820     /* Call the registered callback function */
1821     if (callback != NULL)
1822     {
1823         callback(result, cbArg);
1824     }
1825 }
1826 
1827 /*---------------------------------------------------------------------------*
1828   Name:         SetSndexWork
1829 
1830   Description:  Sets parameters for sndexWork.
1831 
1832   Arguments:    cb: Pointer to the callback function
1833                 cbarg: Argument to pass to 'cb'
1834                 dst: Pointer to a variable to store the command's processing results
1835                 command: Command to send to ARM7
1836 
1837   Returns:      None.
1838  *---------------------------------------------------------------------------*/
1839 static void
SetSndexWork(SNDEXCallback cb,void * cbarg,void * dst,u8 command)1840 SetSndexWork    (SNDEXCallback cb, void* cbarg, void* dst, u8 command)
1841 {
1842     sndexWork.callback = cb;
1843     sndexWork.cbArg = cbarg;
1844     sndexWork.dest = dst;
1845     sndexWork.command = command;
1846 }
1847 
1848 /*---------------------------------------------------------------------------*
1849   Name:         SndexSleepAndExitCallback
1850 
1851   Description:  This callback function is invoked at hardware reset, shutdown, or transition to Sleep Mode.
1852 
1853 
1854   Arguments:    arg
1855 
1856   Returns:      None.
1857  *---------------------------------------------------------------------------*/
1858 static void
SndexSleepAndExitCallback(void * arg)1859 SndexSleepAndExitCallback (void *arg)
1860 {
1861 #pragma unused( arg )
1862     // 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.
1863     //
1864     WaitIirFilterSetting();
1865 
1866     ResetTempVolume();
1867 }
1868 
1869 /*---------------------------------------------------------------------------*
1870   Name:         WaitIirFilterSetting
1871 
1872   Description:  Waits for SNDEX_SetIirFilter[Async] to end.
1873 
1874   Arguments:    None.
1875 
1876   Returns:      None.
1877  *---------------------------------------------------------------------------*/
1878 static void
WaitIirFilterSetting(void)1879 WaitIirFilterSetting (void)
1880 {
1881     // Continue waiting until the SPI_Lock in SNDEX_SetIirFilter[Async] ends
1882     while (isLockSpi)
1883     {
1884         OS_SpinWait(67 * 1000); //Approximately 1 ms
1885         PXIi_HandlerRecvFifoNotEmpty();
1886     }
1887 }
1888 
1889 static void
WaitResetSoundCallback(SNDEXResult result,void * arg)1890 WaitResetSoundCallback(SNDEXResult result, void* arg)
1891 {
1892     static u32 i = 0;    // Retry up to 5 times
1893 #pragma unused(arg)
1894     if (result != SNDEX_RESULT_SUCCESS && i < 5)
1895     {
1896         (void)SNDEXi_SetVolumeExAsync(storeVolume, WaitResetSoundCallback, NULL);
1897         i++;
1898         return;
1899     }
1900     isStoreVolume = FALSE;
1901 }
1902 
1903 /*---------------------------------------------------------------------------*
1904   Name:         ResetTempVolume
1905 
1906   Description:  Reverts to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume.
1907 
1908   Arguments:    None.
1909 
1910   Returns:      None.
1911  *---------------------------------------------------------------------------*/
1912 static void
ResetTempVolume(void)1913 ResetTempVolume (void)
1914 {
1915     if (isStoreVolume)
1916     {
1917         static i = 0;    // Retry up to 5 times
1918         // Revert to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume
1919         // Repeat until the asynchronous function runs successfully
1920         // The callback will handle retries based on the result of changing the volume
1921         while( SNDEX_RESULT_SUCCESS != SNDEXi_SetVolumeExAsync(storeVolume, WaitResetSoundCallback, NULL) && i < 5)
1922         {
1923             i++;
1924         }
1925         while (isStoreVolume)
1926         {
1927             OS_SpinWait(67 * 1000); //Approximately 1 ms
1928             PXIi_HandlerRecvFifoNotEmpty();
1929         }
1930     }
1931 }
1932