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