source: svn/trunk/newcon3bcm2_21bu/magnum/syslib/synclib/7552/bsynclib_audio_source.c

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 12.2 KB
Line 
1/***************************************************************************
2*     Copyright (c) 2004-2010, Broadcom Corporation
3*     All Rights Reserved
4*     Confidential Property of Broadcom Corporation
5*
6*  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7*  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8*  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9*
10* $brcm_Workfile: bsynclib_audio_source.c $
11* $brcm_Revision: Hydra_Software_Devel/9 $
12* $brcm_Date: 5/28/10 6:31p $
13*
14* Revision History:
15*
16* $brcm_Log: /magnum/syslib/synclib/noarch/bsynclib_audio_source.c $
17*
18* Hydra_Software_Devel/9   5/28/10 6:31p bandrews
19* SW7405-4436: printing channel index in dbg messages
20*
21* Hydra_Software_Devel/8   3/22/10 5:43p bandrews
22* sw7405-4083: fix calls to isr
23*
24* Hydra_Software_Devel/7   3/19/10 2:53p bandrews
25* SW7405-3774: merge mute control
26*
27* Hydra_Software_Devel/SW7405-3774/1   2/17/10 6:17p bandrews
28* SW7405-3774: attempt to fix early audio unmute then mute
29*
30* Hydra_Software_Devel/6   2/12/10 8:42p bandrews
31* SW7405-3774: fix handling of sampling rate data so it is edge-based
32*
33* Hydra_Software_Devel/5   2/1/10 8:01p bandrews
34* SW7405-3774: only mute/unmute synchronized sources
35*
36* Hydra_Software_Devel/4   1/26/10 9:00p bandrews
37* SW7405-3774: added mute control support
38*
39* Hydra_Software_Devel/3   8/4/09 4:56p bandrews
40* PR52812: added improved rmd for dmv2
41*
42* Hydra_Software_Devel/2   7/24/09 4:14p bandrews
43* PR52812: Added any-time source or display rate change support
44*
45* Hydra_Software_Devel/1   3/24/08 3:09p bandrews
46* PR40865: Fixed
47*
48* Hydra_Software_Devel/6   2/26/08 10:21p bandrews
49* PR37951: Fixed units.  Implemented static rate mismatch detection.
50*
51* Hydra_Software_Devel/5   2/25/08 9:33p bandrews
52* PR37951: Fixed various bugs
53*
54* Hydra_Software_Devel/4   2/22/08 8:28p bandrews
55* PR37951: Fixed bug in units conversion
56*
57* Hydra_Software_Devel/3   2/20/08 10:03p bandrews
58* PR37951: Updated based on feedback from usage
59*
60* Hydra_Software_Devel/2   1/3/08 5:17p bandrews
61* PR37951: Updated based on initial feedback
62*
63* Hydra_Software_Devel/1   12/12/07 2:53p bandrews
64* PR37951: Initial check-in
65***************************************************************************/
66
67#include "bstd.h"
68#include "bsynclib_priv.h"
69#include "bsynclib_channel_priv.h"
70#include "bsynclib_audio_source.h"
71#include "bsynclib_mute_control.h"
72
73BDBG_MODULE(synclib);
74
75BSYNClib_AudioSource * BSYNClib_AudioSource_Create(void)
76{
77        BSYNClib_AudioSource * psSource = NULL;
78
79        BDBG_ENTER(BSYNClib_AudioSource_Create);
80
81        psSource = (BSYNClib_AudioSource *)BKNI_Malloc(sizeof(BSYNClib_AudioSource));
82
83        if (psSource)
84        {
85                BKNI_Memset(psSource, 0, sizeof(BSYNClib_AudioSource));
86                BSYNClib_DelayElement_Init(&psSource->sElement);
87                BSYNClib_AudioSource_GetDefaultConfig(&psSource->sConfig);
88                BSYNClib_AudioSource_P_GetDefaultStatus(&psSource->sStatus);
89        }
90
91        BDBG_LEAVE(BSYNClib_AudioSource_Create);
92        return psSource;
93}
94
95void BSYNClib_AudioSource_Destroy(BSYNClib_AudioSource * psSource)
96{
97        BDBG_ENTER(BSYNClib_AudioSource_Destroy);
98
99        BDBG_ASSERT(psSource);
100
101        BKNI_Free(psSource);
102
103        BDBG_LEAVE(BSYNClib_AudioSource_Destroy);
104}
105
106bool BSYNClib_AudioSource_SyncCheck(BSYNClib_AudioSource * psSource)
107{
108        bool bPass = false;
109       
110        BDBG_ENTER(BSYNClib_AudioSource_SyncCheck);
111
112        BDBG_ASSERT(psSource);
113
114        bPass = !psSource->sElement.sSnapshot.bSynchronize
115                || (psSource->sElement.sSnapshot.bStarted /* must be started */
116                && psSource->sSnapshot.bSamplingRateReceived /* have received a sampling rate */
117                && psSource->sElement.sDelay.sSnapshot.bValid /* have a valid measured delay */
118                && psSource->sElement.sDelay.sResults.bAccepted); /* and be accepted */
119
120        BDBG_MSG(("[%d] Audio source %u sync check:", psSource->sElement.hParent->iIndex, psSource->sElement.uiIndex));
121        BDBG_MSG(("[%d]  %s", psSource->sElement.hParent->iIndex, psSource->sElement.sSnapshot.bSynchronize ? "synchronized" : "ignored"));
122        BDBG_MSG(("[%d]  %s", psSource->sElement.hParent->iIndex, psSource->sElement.sSnapshot.bStarted ? "started" : "stopped"));
123        BDBG_MSG(("[%d]  sampling rate %s", psSource->sElement.hParent->iIndex, psSource->sSnapshot.bSamplingRateReceived ? "received" : "not received"));
124        BDBG_MSG(("[%d]  delay %s, %s", psSource->sElement.hParent->iIndex, psSource->sElement.sDelay.sSnapshot.bValid ? "valid" : "invalid", 
125                psSource->sElement.sDelay.sResults.bAccepted ? "accepted" : "unaccepted"));
126
127        BDBG_LEAVE(BSYNClib_AudioSource_SyncCheck);
128        return bPass;
129}
130
131void BSYNClib_AudioSource_Reset_isr(BSYNClib_AudioSource * psSource)
132{
133        BDBG_ENTER(BSYNClib_AudioSource_Reset_isr);
134
135        BDBG_ASSERT(psSource);
136
137        psSource->sData.bSamplingRateReceived = false;
138
139        BDBG_LEAVE(BSYNClib_AudioSource_Reset_isr);
140}
141
142BERR_Code BSYNClib_AudioSource_SetMute(BSYNClib_AudioSource * psSource, bool bMute)
143{
144        BERR_Code rc = BERR_SUCCESS;
145        BSYNClib_Channel_Handle hChn;
146        BSYNClib_Channel_MuteCallback * pcbMute;
147
148        BDBG_ENTER(BSYNClib_AudioSource_SetMute);
149       
150        BDBG_ASSERT(psSource);
151       
152        hChn = psSource->sElement.hParent;
153        pcbMute = &hChn->sSettings.sAudio.sSource.cbMute;
154
155        BKNI_EnterCriticalSection();
156        psSource->sResults.bMutePending = false;
157       
158        /* cancel any pending unmute timer */
159        rc = BSYNClib_Channel_P_CancelTimer_isr(hChn, psSource->psUnmuteTimer);
160        BKNI_LeaveCriticalSection();
161        if (rc) goto end;
162
163        /* cancel any pending unconditional unmute timer */
164        if (!bMute)
165        {
166                BKNI_EnterCriticalSection();
167                rc = BSYNClib_Channel_P_CancelTimer_isr(hChn, psSource->psUnconditionalUnmuteTimer);
168                BKNI_LeaveCriticalSection();
169                if (rc) goto end;
170        }
171
172        if (psSource->sConfig.bSynchronize && pcbMute->pfSetMute)/* at mute time, no snapshot has been made */
173        {
174                rc = pcbMute->pfSetMute(pcbMute->pvParm1, pcbMute->iParm2, psSource->sElement.uiIndex, bMute);
175                if(rc) goto end;
176                psSource->sStatus.bMuted = bMute;
177        }
178
179end:
180        BDBG_LEAVE(BSYNClib_AudioSource_SetMute);
181        return rc;
182}
183
184void BSYNClib_AudioSource_GetDefaultConfig(
185        BSYNClib_AudioSource_Config * psConfig
186)
187{
188        BDBG_ENTER(BSYNClib_AudioSource_GetDefaultConfig);
189
190        BDBG_ASSERT(psConfig);
191       
192        BKNI_Memset(psConfig, 0, sizeof(BSYNClib_AudioSource_Config));
193
194        psConfig->bDigital = true;
195
196        BDBG_LEAVE(BSYNClib_AudioSource_GetDefaultConfig);
197}
198
199void BSYNClib_AudioSource_P_SelfClearConfig_isr(
200        BSYNClib_AudioSource * psSource
201)
202{
203        BDBG_ENTER(BSYNClib_AudioSource_P_SelfClearConfig_isr);
204
205        BDBG_ASSERT(psSource);
206       
207        psSource->sConfig.sDelay.bReceived = false;
208        psSource->sConfig.bSamplingRateReceived = false;
209
210        BDBG_LEAVE(BSYNClib_AudioSource_P_SelfClearConfig_isr);
211}
212
213BERR_Code BSYNClib_AudioSource_P_ProcessConfig_isr(
214        BSYNClib_AudioSource * psSource
215)
216{
217        BERR_Code rc = BERR_SUCCESS;
218        BSYNClib_AudioSource_Config * psConfig;
219        BSYNClib_Channel_Handle hChn;
220        bool bChanged = false;
221        bool bScheduleMuteTask = false;
222        BSYNClib_DelayElement sDesired;
223        BSYNClib_DelayElement * psCurrent;
224        BSYNClib_DelayElement_DiffResults sElementDiffResults;
225
226        BDBG_ENTER(BSYNClib_AudioSource_P_ProcessConfig_isr);
227       
228        BDBG_ASSERT(psSource);
229       
230        hChn = psSource->sElement.hParent;
231        psConfig = &psSource->sConfig;
232        psCurrent = &psSource->sElement;
233
234        BKNI_Memset(&sElementDiffResults, 0, sizeof(BSYNClib_DelayElement_DiffResults));
235
236        /* check lifecycle first */
237        BSYNClib_DelayElement_CheckLifecycle_isr(psConfig->bStarted, psCurrent, &sElementDiffResults);
238        if (sElementDiffResults.eLifecycleEvent == BSYNClib_DelayElement_LifecycleEvent_eStarted)
239        {
240                BSYNClib_DelayElement_Reset_isr(psCurrent);
241        }
242
243        /* create "desired" delay element config */
244        sDesired = *psCurrent;
245        sDesired.sData.bStarted = psConfig->bStarted;
246        sDesired.sData.bSynchronize = psConfig->bSynchronize;
247        sDesired.sDelay.sData.uiMeasured = BSYNClib_P_Convert_isr(psConfig->sDelay.sMeasured.uiValue, psConfig->sDelay.sMeasured.eUnits, BSYNClib_Units_e27MhzTicks);
248        sDesired.sDelay.sData.uiCustom = BSYNClib_P_Convert_isr(psConfig->sDelay.sCustom.uiValue, psConfig->sDelay.sCustom.eUnits, BSYNClib_Units_e27MhzTicks);
249        sDesired.sDelay.sData.eOriginalUnits = psConfig->sDelay.sMeasured.eUnits;
250        sDesired.sNotification.sData.bReceived = psConfig->sDelay.bReceived;
251
252        BSYNClib_DelayElement_Diff_isr(&sDesired, &psSource->sElement, &sElementDiffResults);
253
254        if (sElementDiffResults.bChanged)
255        {
256                bChanged = true;
257                BSYNClib_DelayElement_Patch_isr(&sDesired, &psSource->sElement, &sElementDiffResults);
258        }
259
260        /* if we want to synchronize this source, tell mute control */
261        /* must do this on sync change, not on start, otherwise it's too late */
262        switch (sElementDiffResults.eSynchronizationEvent)
263        {
264                case BSYNClib_DelayElement_SynchronizationEvent_eSynchronized:
265                        psSource->sResults.bMutePending = true;
266                        bScheduleMuteTask = true;
267                        break;
268                case BSYNClib_DelayElement_SynchronizationEvent_eIgnored:
269                        psSource->sResults.bMutePending = false;
270                        break;
271                case BSYNClib_DelayElement_SynchronizationEvent_eNone:
272                default:
273                        break;
274        }
275       
276        if (sElementDiffResults.eLifecycleEvent == BSYNClib_DelayElement_LifecycleEvent_eStarted)
277        {
278                /* reset source data */
279                BSYNClib_AudioSource_Reset_isr(psSource);
280
281                /* NOTE: no changing digital on the fly */
282                /* source digital or analog */
283                if (psConfig->bDigital != psSource->sData.bDigital)
284                {
285                        bChanged = true;
286                        psSource->sData.bDigital = psConfig->bDigital;
287                }
288
289                if (psConfig->bSynchronize)
290                {
291                        /* notify mute control of the start of this synchronized source */
292                        bScheduleMuteTask = true;
293                }
294        }
295
296        /* received sampling rate info, edge triggered */
297        if (psConfig->bSamplingRateReceived)
298        {
299                if (!psSource->sData.bSamplingRateReceived)
300                {
301                        bChanged = true;
302                }
303                psSource->sData.bSamplingRateReceived = true;
304        }
305
306        /* all audio delays are accepted immediately */
307        /* TODO: when we add dynamic audio delays, we need to revisit immediate acceptance */
308        if (sElementDiffResults.bDelayReceived)
309        {
310                /* this should not indicate changed */
311                psSource->sElement.sDelay.sResults.bAccepted = true;
312        }
313       
314        if (bChanged)
315        {
316                BDBG_MSG(("[%d] Audio source %u properties changed:", psSource->sElement.hParent->iIndex, psSource->sElement.uiIndex));
317                if (sElementDiffResults.eSynchronizationEvent != BSYNClib_DelayElement_SynchronizationEvent_eNone)
318                {
319                        BDBG_MSG(("[%d]  %s", psSource->sElement.hParent->iIndex, BSYNClib_DelayElement_SynchronizationEventNames[sElementDiffResults.eSynchronizationEvent]));
320                }
321                if (sElementDiffResults.eLifecycleEvent != BSYNClib_DelayElement_LifecycleEvent_eNone)
322                {
323                        BDBG_MSG(("[%d]  %s", psSource->sElement.hParent->iIndex, BSYNClib_DelayElement_LifecycleEventNames[sElementDiffResults.eLifecycleEvent]));
324                }
325                BDBG_MSG(("[%d]  measured delay %u ms", psSource->sElement.hParent->iIndex, BSYNClib_P_Convert_isr(psSource->sElement.sDelay.sData.uiMeasured, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
326                BDBG_MSG(("[%d]  custom delay %u ms", psSource->sElement.hParent->iIndex, BSYNClib_P_Convert_isr(psSource->sElement.sDelay.sData.uiCustom, BSYNClib_Units_e27MhzTicks, BSYNClib_Units_eMilliseconds)));
327                BDBG_MSG(("[%d]  %s", psSource->sElement.hParent->iIndex, psSource->sData.bDigital ? "digital" : "analog"));
328                BDBG_MSG(("[%d]  sampling rate %s", psSource->sElement.hParent->iIndex, psSource->sData.bSamplingRateReceived ? "received" : "not received"));
329                if (psSource->sResults.bMutePending)
330                {
331                                BDBG_MSG(("[%d]  mute pending", psSource->sElement.hParent->iIndex));
332                }
333        }
334
335        if (bScheduleMuteTask)
336        {
337                /* TODO: probably should do this as a dynamic bind so we don't depend upwards, but ... */
338                BSYNClib_MuteControl_ScheduleTask_isr(hChn);
339        }
340
341        if (BSYNClib_Channel_P_Enabled_isr(hChn))
342        {
343        /* if anything changed in the config, reprocess based on current state */
344                if (bChanged)
345        {
346                BSYNClib_Channel_P_ScheduleTask_isr(hChn);
347        }
348        }
349       
350        BDBG_LEAVE(BSYNClib_AudioSource_P_ProcessConfig_isr);
351        return rc;
352}
353
354void BSYNClib_AudioSource_Snapshot_isr(BSYNClib_AudioSource * psSource)
355{
356        BDBG_ENTER(BSYNClib_AudioSource_Snapshot_isr);
357
358        BDBG_ASSERT(psSource);
359
360        psSource->sSnapshot = psSource->sData;
361       
362        BSYNClib_DelayElement_Snapshot_isr(&psSource->sElement);
363
364        BDBG_LEAVE(BSYNClib_AudioSource_Snapshot_isr);
365}
366
367void BSYNClib_AudioSource_P_GetDefaultStatus(
368        BSYNClib_Source_Status * psStatus
369)
370{
371        BDBG_ENTER(BSYNClib_AudioSource_P_GetDefaultStatus);
372
373        BDBG_ASSERT(psStatus);
374
375        psStatus->bMuted = false;
376        psStatus->sDelayNotification.bEnabled = false;
377        psStatus->sDelayNotification.sThreshold.uiValue = 0;
378        psStatus->sAppliedDelay.uiValue = 0;
379
380        BDBG_LEAVE(BSYNClib_AudioSource_P_GetDefaultStatus);
381}
382
Note: See TracBrowser for help on using the repository browser.