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