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