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-04#$
14   $Rev: 10698 $
15   $Author: okubata_ryoma $
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 = eightlv ? SNDEX_GetVolume(&storeVolume) : 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                 This removes the registered termination callback at the same time.
1425 
1426   Arguments:    None.
1427 
1428   Returns:      SNDEXResult: Returns processing results.
1429  *---------------------------------------------------------------------------*/
SNDEXi_ResetIgnoreHWVolume(void)1430 SNDEXResult SNDEXi_ResetIgnoreHWVolume(void)
1431 {
1432     SNDEXResult result;
1433     if ((result = SNDEX_SetVolume(storeVolume)) != SNDEX_RESULT_SUCCESS)
1434     {
1435         return result;
1436     }
1437 
1438     isStoreVolume = FALSE;
1439     return result;          // SNDEX_RESULT_SUCCESS
1440 }
1441 
1442 /*---------------------------------------------------------------------------*
1443   Name:         SNDEXi_PreProcessForShutterSound
1444 
1445   Description:  Performs all the preprocessing necessary for shutter sound playback.
1446                 This is a synchronous function, so calling from inside an interrupt handler is prohibited.
1447 
1448   Arguments:    None.
1449 
1450   Returns:      Returns SNDEX_RESULT_SUCCESS if successful.
1451  *---------------------------------------------------------------------------*/
1452 SNDEXResult
SNDEXi_PreProcessForShutterSound(void)1453 SNDEXi_PreProcessForShutterSound  (void)
1454 {
1455     SNDEXResult     result;
1456     OSMessageQueue  msgQ;
1457     OSMessage       msg[1];
1458 
1459     /* Check CODEC operating mode */
1460     if (OSi_IsCodecTwlMode() == FALSE)
1461     {
1462         return SNDEX_RESULT_ILLEGAL_STATE;
1463     }
1464 
1465     /* Calling this from an exception handler is prohibited */
1466     if (OS_GetCurrentThread() == NULL)
1467     {
1468         SNDEXi_Warning("%s: Syncronous API could not process in exception handler.\n", __FUNCTION__);
1469         return SNDEX_RESULT_ILLEGAL_STATE;
1470     }
1471 
1472     /* Skip CheckState if the SNDEXi_PreProcessForShutterSound function has already been called. */
1473     if (sndexState != SNDEX_STATE_PLAY_SHUTTER)
1474     {
1475         /* Confirm status */
1476         result  =   CheckState();
1477         if (result != SNDEX_RESULT_SUCCESS)
1478         {
1479             return result;
1480         }
1481     }
1482     else if (sndexState == SNDEX_STATE_POST_PROC_SHUTTER)
1483     {
1484         return SNDEX_RESULT_EXCLUSIVE;
1485     }
1486 
1487     /* Initialize the message queue used for synchronization */
1488     OS_InitMessageQueue(&msgQ, msg, 1);
1489 
1490 
1491     /* Register process */
1492     SetSndexWork(SyncCallback, (void*)(&msgQ), NULL, SNDEX_PXI_COMMAND_PRE_PROC_SHUTTER);
1493 
1494     /* Issue command to ARM7 */
1495     if (FALSE == SendCommand(sndexWork.command, 0))
1496     {
1497         return SNDEX_RESULT_PXI_SEND_ERROR;
1498     }
1499 
1500     /* Wait for reply */
1501     (void)OS_ReceiveMessage(&msgQ, (OSMessage*)(&result), OS_MESSAGE_BLOCK);
1502 
1503     return result;
1504 }
1505 
1506 /*---------------------------------------------------------------------------*
1507   Name:         SNDEXi_PostProcessCallbackForShutterSound
1508 
1509   Description:  Executes postprocessing for shutter sound playback.
1510                 This is executed asynchronously because it is executed inside an interrupt.
1511 
1512   Arguments:    callback: Callback function called when the postprocessing completes
1513                 arg: Parameter passed to the callback function
1514 
1515   Returns:      Returns SNDEX_RESULT_SUCCESS if successful.
1516  *---------------------------------------------------------------------------*/
1517 SNDEXResult
SNDEXi_PostProcessForShutterSound(SNDEXCallback callback,void * arg)1518 SNDEXi_PostProcessForShutterSound (SNDEXCallback callback, void* arg)
1519 {
1520     /* Check CODEC operating mode */
1521     // When this function is called, it is presumed to be after execution of SNDEXi_PreProcessCallbackForShutterSound
1522     if (OSi_IsCodecTwlMode() == FALSE || sndexState != SNDEX_STATE_PLAY_SHUTTER)
1523     {
1524         return SNDEX_RESULT_ILLEGAL_STATE;
1525     }
1526 
1527     /* Transition the state to postprocessing (maximum priority) */
1528     sndexState = SNDEX_STATE_POST_PROC_SHUTTER;
1529 
1530     /* Register asynchronous process */
1531     SetSndexWork(callback, arg, NULL, SNDEX_PXI_COMMAND_POST_PROC_SHUTTER);
1532 
1533     /* Issue command to ARM7 */
1534     if (FALSE == SendCommand(sndexWork.command, 0))
1535     {
1536         return SNDEX_RESULT_PXI_SEND_ERROR;
1537     }
1538 
1539     return SNDEX_RESULT_SUCCESS;
1540 }
1541 
1542 /*---------------------------------------------------------------------------*
1543   Name:         CommonCallback
1544 
1545   Description:  PXI FIFO reception callback function for processes related to the extended sound features.
1546 
1547   Arguments:    tag: PXI message type
1548                 data: Message content from ARM7
1549                 err: PXI transfer error flag
1550 
1551   Returns:      None.
1552  *---------------------------------------------------------------------------*/
1553 static void
CommonCallback(PXIFifoTag tag,u32 data,BOOL err)1554 CommonCallback (PXIFifoTag tag, u32 data, BOOL err)
1555 {
1556     u8      command =   (u8)((data & SNDEX_PXI_COMMAND_MASK) >> SNDEX_PXI_COMMAND_SHIFT);
1557     u8      result  =   (u8)((data & SNDEX_PXI_RESULT_MASK) >> SNDEX_PXI_RESULT_SHIFT);
1558     u8      param   =   (u8)((data & SNDEX_PXI_PARAMETER_MASK) >> SNDEX_PXI_PARAMETER_SHIFT);
1559 
1560     /* If the command received from ARM7 is a notification that the system volume switch was pressed, try locking */
1561     if (command == SNDEX_PXI_COMMAND_PRESS_VOLSWITCH)
1562     {
1563         SNDEXResult result = CheckState();
1564         if (result != SNDEX_RESULT_SUCCESS)
1565         {
1566             return;
1567         }
1568         // Set the sndexWork structure
1569         SetSndexWork(NULL, NULL, NULL, SNDEX_PXI_COMMAND_PRESS_VOLSWITCH);
1570     }
1571 
1572     /* Confirm status */
1573     if ((tag != PXI_FIFO_TAG_SNDEX) || (err == TRUE)
1574             || (sndexState != SNDEX_STATE_LOCKED && sndexState != SNDEX_STATE_PLAY_SHUTTER && sndexState != SNDEX_STATE_POST_PROC_SHUTTER)
1575             || (sndexWork.command != command))
1576     {
1577         /* Logically, execution will never be able to pass through here, but output a warning just in case */
1578         OS_TWarning("SNDEX: Library state is inconsistent.\n");
1579         ReplyCallback(SNDEX_RESULT_FATAL_ERROR);
1580         return;
1581     }
1582 
1583     /* Parse the process results */
1584     switch (result)
1585     {
1586     case SNDEX_PXI_RESULT_SUCCESS:
1587         /* Perform completion processing in accordance with the command */
1588         switch (command)
1589         {
1590         case SNDEX_PXI_COMMAND_GET_SMIX_MUTE:
1591             if (sndexWork.dest != NULL)
1592             {
1593                 *((SNDEXMute*)sndexWork.dest)   = (SNDEXMute)param;
1594             }
1595             break;
1596         case SNDEX_PXI_COMMAND_GET_SMIX_FREQ:
1597             if (sndexWork.dest != NULL)
1598             {
1599                 *((SNDEXFrequency*)sndexWork.dest)  =   (SNDEXFrequency)param;
1600             }
1601             break;
1602         case SNDEX_PXI_COMMAND_GET_SMIX_DSP:
1603         case SNDEX_PXI_COMMAND_GET_VOLUME:
1604             if (sndexWork.dest != NULL)
1605             {
1606                 *((u8*)sndexWork.dest)  =   param;
1607             }
1608             break;
1609         case SNDEX_PXI_COMMAND_GET_SND_DEVICE:
1610             if (sndexWork.dest != NULL)
1611             {
1612                 *((SNDEXDevice*)sndexWork.dest) =   (SNDEXDevice)param;
1613             }
1614             break;
1615         case SNDEX_PXI_COMMAND_PRESS_VOLSWITCH:
1616             /* Notification from ARM7 that the volume button was pressed */
1617             if (SNDEXi_VolumeSwitchCallbackInfo.callback != NULL)
1618             {
1619                 (SNDEXi_VolumeSwitchCallbackInfo.callback)((SNDEXResult)result, SNDEXi_VolumeSwitchCallbackInfo.cbArg);
1620             }
1621             break;
1622         case SNDEX_PXI_COMMAND_HP_CONNECT:
1623             if (sndexWork.dest != NULL)
1624             {
1625                 *((SNDEXHeadphone*)sndexWork.dest) =   (SNDEXHeadphone)param;
1626             }
1627             break;
1628         }
1629         ReplyCallback(SNDEX_RESULT_SUCCESS);
1630         break;
1631     case SNDEX_PXI_RESULT_INVALID_PARAM:
1632         ReplyCallback(SNDEX_RESULT_INVALID_PARAM);
1633         break;
1634     case SNDEX_PXI_RESULT_EXCLUSIVE:
1635         ReplyCallback(SNDEX_RESULT_EXCLUSIVE);
1636         break;
1637     case SNDEX_PXI_RESULT_ILLEGAL_STATE:
1638         ReplyCallback(SNDEX_RESULT_ILLEGAL_STATE);
1639         break;
1640     case SNDEX_PXI_RESULT_DEVICE_ERROR:
1641         if (command == SNDEX_PXI_COMMAND_GET_VOLUME)
1642         {
1643             if (sndexWork.dest != NULL)
1644             {
1645                 *((u8*)sndexWork.dest)  =   SNDEX_VOLUME_MIN;
1646             }
1647         }
1648         ReplyCallback(SNDEX_RESULT_DEVICE_ERROR);
1649         break;
1650     case SNDEX_PXI_RESULT_INVALID_COMMAND:
1651     default:
1652         ReplyCallback(SNDEX_RESULT_FATAL_ERROR);
1653         break;
1654     }
1655 }
1656 
1657 /*---------------------------------------------------------------------------*
1658   Name:         SyncCallback
1659 
1660   Description:  Shared callback function for synchronous function control.
1661 
1662   Arguments:    result: Result of asynchronous processing
1663                 arg: Message being blocked by the synchronous function while it waits for reception.
1664                             Pointer to queue control structure.
1665 
1666   Returns:      None.
1667  *---------------------------------------------------------------------------*/
1668 static void
SyncCallback(SNDEXResult result,void * arg)1669 SyncCallback (SNDEXResult result, void* arg)
1670 {
1671     SDK_NULL_ASSERT(arg);
1672 
1673     if (FALSE == OS_SendMessage((OSMessageQueue*)arg, (OSMessage)result, OS_MESSAGE_NOBLOCK))
1674     {
1675         /* Logically, execution will never be able to pass through here, but output a warning just in case */
1676         OS_TWarning("SNDEX: Temporary message queue is full.\n");
1677     }
1678 }
1679 
1680 /*---------------------------------------------------------------------------*
1681   Name:         SendCommand
1682 
1683   Description:  Issues an extended sound feature operation command to ARM7 via PXI.
1684 
1685   Arguments:    command: Command type
1686                 param: Parameter associated with the command
1687 
1688   Returns:      BOOL: Returns TRUE if PXI transmission was successful.
1689  *---------------------------------------------------------------------------*/
1690 static BOOL
SendCommand(u8 command,u8 param)1691 SendCommand (u8 command, u8 param)
1692 {
1693     OSIntrMode  e   =   OS_DisableInterrupts();
1694     u32     packet  =   (u32)(((command << SNDEX_PXI_COMMAND_SHIFT) & SNDEX_PXI_COMMAND_MASK)
1695                         | ((param << SNDEX_PXI_PARAMETER_SHIFT) & SNDEX_PXI_PARAMETER_MASK));
1696 
1697     if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_SNDEX, packet, 0))
1698     {
1699         /* Lift exclusion controls if transmission failed */
1700         sndexState  =   SNDEX_STATE_INITIALIZED;
1701         (void)OS_RestoreInterrupts(e);
1702         SNDEXi_Warning("SNDEX: Failed to send PXI command.\n");
1703         return FALSE;
1704     }
1705 
1706     (void)OS_RestoreInterrupts(e);
1707     return TRUE;
1708 }
1709 
1710 /*---------------------------------------------------------------------------*
1711   Name:         SendCommand
1712 
1713   Description:  Issues an extended sound feature operation command to ARM7 via PXI.
1714 
1715   Arguments:    command: Command type
1716                 param: Parameter associated with the command (16 bits because of the IirFilter parameter)
1717 
1718   Returns:      BOOL: Returns TRUE if PXI transmission was successful.
1719  *---------------------------------------------------------------------------*/
1720 static BOOL
SendCommandEx(u8 command,u16 param)1721 SendCommandEx (u8 command, u16 param)
1722 {
1723     OSIntrMode  e   =   OS_DisableInterrupts();
1724     u32     packet  =   (u32)(((command << SNDEX_PXI_COMMAND_SHIFT) & SNDEX_PXI_COMMAND_MASK)
1725                         | ((param << SNDEX_PXI_PARAMETER_SHIFT) & SNDEX_PXI_PARAMETER_MASK_IIR));
1726 
1727     if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_SNDEX, packet, 0))
1728     {
1729         /* Lift exclusion controls if transmission failed */
1730         sndexState  =  SNDEX_STATE_INITIALIZED;
1731         (void)OS_RestoreInterrupts(e);
1732         SNDEXi_Warning("SNDEX: Failed to send PXI command.\n");
1733         return FALSE;
1734     }
1735     if( command == SNDEX_PXI_COMMAND_SET_IIRFILTER )
1736     {
1737         isLockSpi = TRUE;
1738     }
1739 
1740     (void)OS_RestoreInterrupts(e);
1741     return TRUE;
1742 }
1743 
1744 /*---------------------------------------------------------------------------*
1745   Name:         CheckState
1746 
1747   Description:  Checks whether the internal state is one where an asynchronous process can start, and if so, locks the SNDEX library.
1748 
1749 
1750   Arguments:    None.
1751 
1752   Returns:      None.
1753  *---------------------------------------------------------------------------*/
1754 static SNDEXResult
CheckState(void)1755 CheckState (void)
1756 {
1757     OSIntrMode  e   =   OS_DisableInterrupts();
1758 
1759     /* Check internal state */
1760     switch (sndexState)
1761     {
1762     case SNDEX_STATE_BEFORE_INIT:
1763     case SNDEX_STATE_INITIALIZING:
1764         (void)OS_RestoreInterrupts(e);
1765         SNDEXi_Warning("SNDEX: Library is not initialized yet.\n");
1766         return SNDEX_RESULT_BEFORE_INIT;
1767     case SNDEX_STATE_LOCKED:
1768     case SNDEX_STATE_PLAY_SHUTTER:
1769     case SNDEX_STATE_POST_PROC_SHUTTER:
1770         (void)OS_RestoreInterrupts(e);
1771         SNDEXi_Warning("SNDEX: Another request is in progress.\n");
1772         return SNDEX_RESULT_EXCLUSIVE;
1773     }
1774 
1775     /* Transition to state where exclusion control is in effect */
1776     sndexState  =   SNDEX_STATE_LOCKED;
1777     (void)OS_RestoreInterrupts(e);
1778     return SNDEX_RESULT_SUCCESS;
1779 }
1780 
1781 /*---------------------------------------------------------------------------*
1782   Name:         ReplyCallback
1783 
1784   Description:  Sends notification of the completion of asynchronous processing. Updates the internal sate and also lifts the exclusion state.
1785 
1786 
1787   Arguments:    result: Asynchronous processing result to notify to the callback function
1788 
1789   Returns:      None.
1790  *---------------------------------------------------------------------------*/
1791 static void
ReplyCallback(SNDEXResult result)1792 ReplyCallback (SNDEXResult result)
1793 {
1794     OSIntrMode      e           =   OS_DisableInterrupts();
1795     SNDEXCallback   callback    =   sndexWork.callback;
1796     void*           cbArg       =   sndexWork.cbArg;
1797     u8              command     =   sndexWork.command;
1798 
1799     // Assume that the SPI_Lock was ended by SetIirFilterAsync, and lower the flag
1800     if (sndexWork.command == SNDEX_PXI_COMMAND_SET_IIRFILTER)
1801     {
1802         isLockSpi = FALSE;
1803         isIirFilterSetting = FALSE;
1804     }
1805 
1806     /* Reset state */
1807     SetSndexWork(NULL, NULL, NULL, 0);
1808     // If currently preprocessing the shutter sound playback, do not unlock until postprocessing begins
1809     if (command == SNDEX_PXI_COMMAND_PRE_PROC_SHUTTER)
1810     {
1811         // Anything other than the SNDEXi_PostProcessForShutterSound function, which performs shutter sound playback postprocessing, is considered locked and is excluded.
1812         //
1813         sndexState          =   SNDEX_STATE_PLAY_SHUTTER;
1814     }
1815     else
1816     {
1817         sndexState          =   SNDEX_STATE_INITIALIZED;
1818     }
1819     (void)OS_RestoreInterrupts(e);
1820 
1821     /* Call the registered callback function */
1822     if (callback != NULL)
1823     {
1824         callback(result, cbArg);
1825     }
1826 }
1827 
1828 /*---------------------------------------------------------------------------*
1829   Name:         SetSndexWork
1830 
1831   Description:  Sets parameters for sndexWork.
1832 
1833   Arguments:    cb: Pointer to the callback function
1834                 cbarg: Argument to pass to 'cb'
1835                 dst: Pointer to a variable to store the command's processing results
1836                 command: Command to send to ARM7
1837 
1838   Returns:      None.
1839  *---------------------------------------------------------------------------*/
1840 static void
SetSndexWork(SNDEXCallback cb,void * cbarg,void * dst,u8 command)1841 SetSndexWork    (SNDEXCallback cb, void* cbarg, void* dst, u8 command)
1842 {
1843     sndexWork.callback = cb;
1844     sndexWork.cbArg = cbarg;
1845     sndexWork.dest = dst;
1846     sndexWork.command = command;
1847 }
1848 
1849 /*---------------------------------------------------------------------------*
1850   Name:         SndexSleepAndExitCallback
1851 
1852   Description:  This callback function is invoked at hardware reset, shutdown, or transition to Sleep Mode.
1853 
1854 
1855   Arguments:    arg
1856 
1857   Returns:      None.
1858  *---------------------------------------------------------------------------*/
1859 static void
SndexSleepAndExitCallback(void * arg)1860 SndexSleepAndExitCallback (void *arg)
1861 {
1862 #pragma unused( arg )
1863     // 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.
1864     //
1865     WaitIirFilterSetting();
1866 
1867     ResetTempVolume();
1868 }
1869 
1870 /*---------------------------------------------------------------------------*
1871   Name:         WaitIirFilterSetting
1872 
1873   Description:  Waits for SNDEX_SetIirFilter[Async] to end.
1874 
1875   Arguments:    None.
1876 
1877   Returns:      None.
1878  *---------------------------------------------------------------------------*/
1879 static void
WaitIirFilterSetting(void)1880 WaitIirFilterSetting (void)
1881 {
1882     // Continue waiting until the SPI_Lock in SNDEX_SetIirFilter[Async] ends
1883     while (isLockSpi)
1884     {
1885         OS_SpinWait(67 * 1000); //Approximately 1 ms
1886         PXIi_HandlerRecvFifoNotEmpty();
1887     }
1888 }
1889 
1890 static void
WaitResetSoundCallback(SNDEXResult result,void * arg)1891 WaitResetSoundCallback(SNDEXResult result, void* arg)
1892 {
1893     static u32 i = 0;    // Retry up to 5 times
1894 #pragma unused(arg)
1895     if (result != SNDEX_RESULT_SUCCESS && i < 5)
1896     {
1897         (void)SNDEX_SetVolumeAsync(storeVolume, WaitResetSoundCallback, NULL);
1898         i++;
1899         return;
1900     }
1901     isStoreVolume = FALSE;
1902 }
1903 
1904 /*---------------------------------------------------------------------------*
1905   Name:         ResetTempVolume
1906 
1907   Description:  Reverts to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume.
1908 
1909   Arguments:    None.
1910 
1911   Returns:      None.
1912  *---------------------------------------------------------------------------*/
1913 static void
ResetTempVolume(void)1914 ResetTempVolume (void)
1915 {
1916     if (isStoreVolume)
1917     {
1918         static i = 0;    // Retry up to 5 times
1919         // Revert to the volume that was temporarily saved by SNDEXi_SetIgnoreHWVolume
1920         // Repeat until the asynchronous function runs successfully
1921         // The callback will handle retries based on the result of changing the volume
1922         while( SNDEX_RESULT_SUCCESS != SNDEX_SetVolumeAsync(storeVolume, WaitResetSoundCallback, NULL) && i < 5)
1923         {
1924             i++;
1925         }
1926         while (isStoreVolume)
1927         {
1928             OS_SpinWait(67 * 1000); //Approximately 1 ms
1929             PXIi_HandlerRecvFifoNotEmpty();
1930         }
1931     }
1932 }
1933