source: svn/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_mixer_standard.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 72.7 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2006-2012, 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: bape_mixer_standard.c $
11 * $brcm_Revision: Hydra_Software_Devel/15 $
12 * $brcm_Date: 3/22/12 4:27p $
13 *
14 * Module Description: Mixer Interface for "Standard" Mixers
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/ape/7422/bape_mixer_standard.c $
19 *
20 * Hydra_Software_Devel/15   3/22/12 4:27p jgarrett
21 * SW7425-2644: Ensuring output format is set properly with only a single
22 * input
23 *
24 * Hydra_Software_Devel/14   2/16/12 3:00p jgarrett
25 * SW7552-188: Removing dummy mixer outputs.  MAI CBIT formatting no
26 * longer requires this
27 *
28 * Hydra_Software_Devel/13   2/13/12 10:41a jgarrett
29 * SW7425-2377: Adding check for output delay out of range
30 *
31 * Hydra_Software_Devel/12   1/27/12 5:12p jgarrett
32 * SW7429-55: Revising MCLK selection to handle 7429 case with a DAC and
33 * other outputs.  Also forcing default sample rate to be set prior to
34 * enabling any outputs.
35 *
36 * Hydra_Software_Devel/11   12/13/11 5:34p jgarrett
37 * SW7425-1648: Adding support for mixing compressed sources
38 *
39 * Hydra_Software_Devel/10   12/2/11 3:19p jgarrett
40 * SW7346-578: Adding ability to change some mixer settings without
41 * destroying and re-creating the mixer
42 *
43 * Hydra_Software_Devel/9   8/23/11 1:23p gskerl
44 * SW7425-1119: Added prototypes and stubs for BAPE_Mixer_Start() and
45 * BAPE_Mixer_Stop(). For now, they just return BERR_NOT_SUPPORTED
46 *
47 * Hydra_Software_Devel/8   8/2/11 3:27p jgarrett
48 * SWDTV-8150: Adding mixer output connection support
49 *
50 * Hydra_Software_Devel/7   7/11/11 4:56p gskerl
51 * SW7425-884: Corrected arguments passed to BAPE_P_DetachMixerFromPll and
52 * BAPE_P_DetachMixerFromNco
53 *
54 * Hydra_Software_Devel/6   7/8/11 4:32p gskerl
55 * SW7552-72: Added support for NCO/Mclkgen audio clock sources
56 *
57 * Hydra_Software_Devel/5   6/27/11 6:11p jgarrett
58 * SW7344-84: Not applying volume coefficients to compressed inputs of
59 * mixers
60 *
61 * Hydra_Software_Devel/4   6/27/11 5:41p jgarrett
62 * SW7231-97: Refactoring SPDIF/HDMI enable mechanisms to handle older
63 * Onkyo receiver DTS->PCM switching requirements
64 *
65 * Hydra_Software_Devel/3   6/6/11 1:13p gskerl
66 * SW7425-321: Added comments
67 *
68 * Hydra_Software_Devel/2   5/31/11 6:37p jgarrett
69 * SW7425-406: Adding initial DSP mixer code
70 *
71 * Hydra_Software_Devel/1   5/27/11 7:50p gskerl
72 * SW7425-321: Split mixer code into multiple files. Added framework for
73 * dispatching mixer API calls to multiple mixer types.
74 *
75 *
76 * Hydra_Software_Devel/26   5/26/11 5:38p jgarrett
77 * SW7346-224: Making sure buffers are validated even if mixer path is
78 * cached.  Removing other connections may have removed buffers.
79 *
80 * Hydra_Software_Devel/SW7425-321/2   5/27/11 7:06p gskerl
81 * SW7425-321: Changed names of BAPE_MixerInterface members. Changed
82 * BAPE_Mixer.interface from struct to pointer.
83 *
84 * Hydra_Software_Devel/SW7425-321/1   5/27/11 4:24p gskerl
85 * SW7425-321: Split mixer code into multiple files. Added framework for
86 * dispatching mixer API calls to multiple mixer types.
87 *
88 * Hydra_Software_Devel/1   12/16/10 4:05p jgarrett
89 * SW7422-146: Initial compilable APE for 7422
90 *
91 ***************************************************************************/
92
93#include "bstd.h"
94#include "bkni.h"
95#include "bape.h"
96#include "bape_priv.h"
97
98BDBG_MODULE(bape_mixer);
99BDBG_FILE_MODULE(bape_mixer_get_mclk_source);
100
101#define BAPE_MIXER_INPUT_INDEX_INVALID ((unsigned)-1)
102
103/* Local function prototypes */
104static void BAPE_StandardMixer_P_SetSampleRate_isr(BAPE_MixerHandle mixer, unsigned sampleRate);
105static void BAPE_StandardMixer_P_SetInputSRC_isr(BAPE_MixerHandle mixer, BAPE_Connector input, unsigned inputRate, unsigned outputRate);
106static BERR_Code BAPE_StandardMixer_P_RemoveAllInputs( BAPE_MixerHandle handle );
107static BERR_Code BAPE_StandardMixer_P_RemoveAllOutputs( BAPE_MixerHandle handle );
108static bool BAPE_StandardMixer_P_ValidateSettings(const BAPE_MixerSettings *pSettings);
109
110/* Node callbacks */
111static BERR_Code BAPE_StandardMixer_P_AllocatePathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
112static void      BAPE_StandardMixer_P_FreePathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
113static BERR_Code BAPE_StandardMixer_P_ConfigPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
114static BERR_Code BAPE_StandardMixer_P_StartPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
115static void      BAPE_StandardMixer_P_StopPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
116static BERR_Code BAPE_StandardMixer_P_OutputConnectionAdded(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
117static void      BAPE_StandardMixer_P_OutputConnectionRemoved(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection); 
118static void      BAPE_StandardMixer_P_InputSampleRateChange_isr(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
119static BERR_Code BAPE_StandardMixer_P_InputFormatChange(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
120static void      BAPE_StandardMixer_P_InputMute(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection, bool enabled);
121static BERR_Code BAPE_StandardMixer_P_ConnectorSupported(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector);
122static void      BAPE_StandardMixer_P_RemoveInputCallback(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector);
123
124/* Resource routines */
125static BERR_Code BAPE_StandardMixer_P_AllocateResources(BAPE_MixerHandle mixer);
126static BERR_Code BAPE_StandardMixer_P_AllocateConnectionResources(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection);
127static void BAPE_StandardMixer_P_FreeConnectionResources(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection);
128static void BAPE_StandardMixer_P_FreeResources(BAPE_MixerHandle handle);
129static BERR_Code BAPE_StandardMixer_P_AllocateMixerGroups(BAPE_MixerHandle handle);
130
131/* Define the interface struct with all the API callbacks.   It's declared and
132 * populated at the bottom of this file.  */
133static const BAPE_MixerInterface  standardMixerInterface;     
134
135
136/*************************************************************************/
137BERR_Code BAPE_StandardMixer_P_Create(
138    BAPE_Handle deviceHandle,
139    const BAPE_MixerSettings *pSettings,
140    BAPE_MixerHandle *pHandle               /* [out] */
141    )
142{
143    BAPE_MixerHandle handle;
144    BAPE_MixerSettings defaultSettings;
145
146    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
147    BDBG_ASSERT(NULL != pHandle);
148
149    *pHandle = NULL;
150
151    if ( NULL == pSettings )
152    {
153        BAPE_Mixer_GetDefaultSettings(&defaultSettings);
154        pSettings = &defaultSettings;
155    }
156   
157    /* Make sure settings are valid */
158    if ( !BAPE_StandardMixer_P_ValidateSettings(pSettings) )
159    {
160        return BERR_TRACE(BERR_INVALID_PARAMETER);
161    }
162
163    handle = BKNI_Malloc(sizeof(BAPE_Mixer));
164    if ( NULL == handle )
165    {
166        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
167    }
168
169    BKNI_Memset(handle, 0, sizeof(BAPE_Mixer));
170    BDBG_OBJECT_SET(handle, BAPE_Mixer);
171    handle->settings = *pSettings;
172    handle->interface = &standardMixerInterface;
173    handle->deviceHandle = deviceHandle;
174    BLST_S_INSERT_HEAD(&deviceHandle->mixerList, handle, node);
175    handle->sampleRate = 0;
176    handle->fs = BAPE_FS_INVALID;
177    BAPE_P_InitPathNode(&handle->pathNode, BAPE_PathNodeType_eMixer, handle->settings.type, 1, deviceHandle, handle);
178    handle->pathNode.subtype = BAPE_MixerType_eStandard;
179    handle->pathNode.pName = "Standard Mixer";
180    handle->pathNode.paths[0].connector.dataSource = BAPE_DataSource_eFci;
181    handle->pathNode.paths[0].connector.numChannelPairs = 1;
182    /* Fill in node connection routines */
183    handle->pathNode.allocatePathFromInput = BAPE_StandardMixer_P_AllocatePathFromInput;
184    handle->pathNode.freePathFromInput = BAPE_StandardMixer_P_FreePathFromInput;
185    handle->pathNode.configPathFromInput = BAPE_StandardMixer_P_ConfigPathFromInput;
186    handle->pathNode.startPathFromInput = BAPE_StandardMixer_P_StartPathFromInput;
187    handle->pathNode.stopPathFromInput = BAPE_StandardMixer_P_StopPathFromInput;
188    handle->pathNode.outputConnectionAdded = BAPE_StandardMixer_P_OutputConnectionAdded;
189    handle->pathNode.outputConnectionRemoved = BAPE_StandardMixer_P_OutputConnectionRemoved;
190    handle->pathNode.inputSampleRateChange_isr = BAPE_StandardMixer_P_InputSampleRateChange_isr;
191    handle->pathNode.inputFormatChange = BAPE_StandardMixer_P_InputFormatChange;
192    handle->pathNode.inputMute = BAPE_StandardMixer_P_InputMute;
193    handle->pathNode.connectorSupported = BAPE_StandardMixer_P_ConnectorSupported;
194    handle->pathNode.removeInput = BAPE_StandardMixer_P_RemoveInputCallback;
195
196    *pHandle = handle;
197
198    return BERR_SUCCESS;
199}
200
201
202/*************************************************************************/
203static void BAPE_StandardMixer_P_Destroy(
204    BAPE_MixerHandle handle
205    )
206{
207    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
208   
209    /* Make sure no inputs are running. */
210    if ( handle->running )
211    {
212        BDBG_ERR(("Mixer %p (%d) is running.  Cannot close.", handle, handle->index));
213        BDBG_ASSERT(false == handle->running);
214        return;
215    }
216
217    /* Remove all inputs */
218    BAPE_StandardMixer_P_RemoveAllInputs(handle);
219
220    /* Remove all outputs */
221    BAPE_StandardMixer_P_RemoveAllOutputs(handle);
222
223    /* Break any downstream connections */
224    BAPE_Connector_P_RemoveAllConnections(&handle->pathNode.paths[0].connector);
225   
226    /* Unlink from device */
227    BLST_S_REMOVE(&handle->deviceHandle->mixerList, handle, BAPE_Mixer, node);
228    BDBG_OBJECT_DESTROY(handle, BAPE_Mixer);
229    BKNI_Free(handle);
230}
231
232
233/*************************************************************************/
234static BERR_Code BAPE_StandardMixer_P_AddInput(
235    BAPE_MixerHandle handle,
236    BAPE_Connector input,
237    const BAPE_MixerAddInputSettings *pSettings     /* Optional, pass NULL for default settings */
238    )
239{
240    unsigned i;
241    BERR_Code errCode;
242    BAPE_MixerAddInputSettings defaultSettings;
243    bool makeMaster;
244
245    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
246    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
247
248    if ( NULL == pSettings )
249    {
250        pSettings = &defaultSettings;
251        BAPE_Mixer_GetDefaultAddInputSettings(&defaultSettings);
252    }
253
254    makeMaster = pSettings->sampleRateMaster;
255
256    if ( handle->running )
257    {
258        BDBG_ERR(("Cannot change inputs while a mixer is active."));
259        return BERR_TRACE(BERR_NOT_SUPPORTED);
260    }
261
262#if BDBG_DEBUG_BUILD
263    /* Make sure the same input isn't added multiple times */
264    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
265    {
266        if ( handle->inputs[i] == input )
267        {
268            BDBG_ERR(("Cannot add the same input multiple times to a single mixer."));
269            return BERR_TRACE(BERR_NOT_SUPPORTED);
270        }
271    }
272#endif
273
274    /* Find empty slot */
275    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
276    {
277        if ( handle->inputs[i] == NULL )
278        {
279            handle->inputs[i] = input;
280            BDBG_MSG(("Adding input %s to mixer %u as %s", input->pName, handle->index, makeMaster?"master":"slave"));
281            if ( makeMaster )
282            {
283                if ( handle->master )
284                {
285                    BDBG_WRN(("Replacing current master input with new input"));
286                }
287                handle->master = input;
288            }
289            BAPE_Mixer_P_GetDefaultInputVolume(&handle->inputVolume[i]);
290            errCode = BAPE_PathNode_P_AddInput(&handle->pathNode, input);
291            if ( errCode )
292            {
293                handle->inputs[i] = NULL;
294                return BERR_TRACE(errCode);
295            }
296            return BERR_SUCCESS;
297        }
298    }
299
300    /* Mixer has no available slots. */
301    BDBG_ERR(("Mixer can not accept any more inputs.  Maximum inputs per mixer is %u.", BAPE_CHIP_MAX_MIXER_INPUTS));
302    return BERR_TRACE(BERR_NOT_SUPPORTED);
303}
304
305
306/*************************************************************************/
307static BERR_Code BAPE_StandardMixer_P_RemoveInput(
308    BAPE_MixerHandle handle,
309    BAPE_Connector input
310    )
311{
312    unsigned i;
313    BERR_Code errCode;
314
315    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
316    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
317
318    if ( handle->running )
319    {
320        BDBG_ERR(("Cannot change inputs while a mixer is active."));
321        return BERR_TRACE(BERR_NOT_SUPPORTED);
322    }
323
324    /* Find slot containing this input */
325    i = BAPE_Mixer_P_FindInputIndex(handle, input);
326    if ( i < BAPE_CHIP_MAX_MIXER_INPUTS )
327    {
328        errCode = BAPE_PathNode_P_RemoveInput(&handle->pathNode, input);
329        if ( errCode )
330        {
331            return BERR_TRACE(errCode);
332        }
333        handle->inputs[i] = NULL;
334        if ( handle->master == input )
335        {
336            BDBG_MSG(("Removing master input %p", input));
337            handle->master = NULL;
338        }
339        return BERR_SUCCESS;
340    }
341
342    /* Input not found. */
343    BDBG_ERR(("Input %p is not connected to mixer %p", input, handle));
344    return BERR_TRACE(BERR_INVALID_PARAMETER);
345}
346
347
348/*************************************************************************/
349static BERR_Code BAPE_StandardMixer_P_RemoveAllInputs(
350    BAPE_MixerHandle handle
351    )
352{
353    unsigned i;
354    BERR_Code errCode;
355
356    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
357
358    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
359    {
360        if ( handle->inputs[i] )
361        {
362            errCode = BAPE_StandardMixer_P_RemoveInput(handle, handle->inputs[i]);
363            if ( errCode )
364            {
365                return BERR_TRACE(errCode);
366            }
367        }
368    }
369
370    return BERR_SUCCESS;
371}
372
373
374/*************************************************************************/
375static BERR_Code BAPE_StandardMixer_P_AddOutput(
376    BAPE_MixerHandle handle,
377    BAPE_OutputPort output
378    )
379{
380    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
381    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
382
383    if ( output->mixer )
384    {
385        BDBG_ERR(("Output %p is already connected to mixer %p", output, output->mixer));
386        return BERR_TRACE(BERR_INVALID_PARAMETER);
387    }
388
389    if ( handle->running )
390    {
391        return BERR_TRACE(BERR_NOT_SUPPORTED);
392    }
393    else
394    {
395        /* Bind mixer and output.  Remainder is done at start time. */
396        output->mixer = handle;
397        BLST_S_INSERT_HEAD(&handle->outputList, output, node);
398        handle->numOutputs++;
399        output->sourceMixerGroup = NULL;
400        output->sourceMixerOutputIndex = 0;
401        BAPE_StandardMixer_P_FreeResources(handle);
402   
403        BDBG_MSG(("Added output %p '%s' to mixer %u [mixer rate %u]", output, output->pName, handle->index, handle->sampleRate));
404        if ( output->setTimingParams_isr && handle->sampleRate != 0 )
405        {
406            output->setTimingParams_isr(output, handle->sampleRate, handle->settings.outputTimebase);
407        }
408    }
409
410    return BERR_SUCCESS;
411}
412
413
414/*************************************************************************/
415static BERR_Code BAPE_StandardMixer_P_RemoveOutput(
416    BAPE_MixerHandle handle,
417    BAPE_OutputPort output
418    )
419{
420    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
421    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
422
423    if ( output->mixer != handle )
424    {
425        BDBG_ERR(("Output %p is not connected to mixer %p"));
426        return BERR_TRACE(BERR_INVALID_PARAMETER);
427    }
428
429    if ( handle->running )
430    {
431        return BERR_TRACE(BERR_NOT_SUPPORTED);
432    }
433    else
434    {
435        /* Release mixer-level resources and rebuild on the next start */
436        BAPE_StandardMixer_P_FreeResources(handle);
437        output->mixer = NULL;
438        BLST_S_REMOVE(&handle->outputList, output, BAPE_OutputPortObject, node);
439        BDBG_ASSERT(handle->numOutputs > 0);
440        handle->numOutputs--;
441        BDBG_MSG(("Removed output %p '%s' from mixer %u [mixer rate %u]", output, output->pName, handle->index, handle->sampleRate));
442    }
443
444    return BERR_SUCCESS;
445}
446
447
448/*************************************************************************/
449static BERR_Code BAPE_StandardMixer_P_RemoveAllOutputs(
450    BAPE_MixerHandle handle
451    )
452{
453    BAPE_OutputPort output;
454    BERR_Code errCode;
455
456    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
457
458    while ( (output=BLST_S_FIRST(&handle->outputList)) )
459    {
460        errCode = BAPE_StandardMixer_P_RemoveOutput(handle, output);
461        if ( errCode )
462        {
463            return BERR_TRACE(errCode);
464        }
465    }
466
467    return BERR_SUCCESS;
468}
469
470
471/*************************************************************************/
472static BERR_Code BAPE_StandardMixer_P_GetInputVolume(
473    BAPE_MixerHandle handle,
474    BAPE_Connector input,
475    BAPE_MixerInputVolume *pVolume      /* [out] */
476    )
477{
478    unsigned i;
479
480    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
481    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
482    BDBG_ASSERT(NULL != pVolume);
483
484    i = BAPE_Mixer_P_FindInputIndex(handle, input);
485    if ( i == BAPE_MIXER_INPUT_INDEX_INVALID )
486    {
487        BDBG_ERR(("Input %p is not connected to mixer %p", input, handle));
488        return BERR_TRACE(BERR_INVALID_PARAMETER);
489    }
490
491    *pVolume = handle->inputVolume[i];
492
493    return BERR_SUCCESS;
494}
495
496
497/*************************************************************************/
498static BERR_Code BAPE_StandardMixer_P_ApplyInputVolume(BAPE_MixerHandle mixer, unsigned index)
499{
500    BAPE_MixerGroupInputSettings mixerInputSettings;
501    BAPE_Connector source = mixer->inputs[index];
502    unsigned mixerNum;
503    unsigned i;
504    BERR_Code errCode;
505
506    BDBG_OBJECT_ASSERT(source, BAPE_PathConnector);
507
508    for ( mixerNum = 0; mixerNum < BAPE_CHIP_MAX_MIXERS; mixerNum++ )
509    {
510        BAPE_MixerGroupHandle mixerGroup = mixer->mixerGroups[mixerNum];
511        if ( NULL != mixerGroup )
512        {
513            BAPE_MixerGroup_P_GetInputSettings(mixerGroup, index, &mixerInputSettings);
514            for ( i = 0; i < BAPE_ChannelPair_eMax; i++ )
515            {
516                if ( source->compressed && !mixer->inputMuted[index] )
517                {
518                    /* Compressed inputs must be either full-scale or 0 coefficients. */
519                    int32_t coef = source->numChannelPairs > i ? BAPE_VOLUME_NORMAL : 0;
520                    mixerInputSettings.coefficients[i][0][0] = coef;
521                    mixerInputSettings.coefficients[i][1][0] = 0;
522                    mixerInputSettings.coefficients[i][0][1] = 0;
523                    mixerInputSettings.coefficients[i][1][1] = coef;
524                }
525                else if ( source->numChannelPairs > i && !mixer->inputMuted[index] && !mixer->inputVolume[index].muted )
526                {
527                    /* PCM inputs can have variable volume */
528                    mixerInputSettings.coefficients[i][0][0] = mixer->inputVolume[index].coefficients[2*i][2*i];
529                    mixerInputSettings.coefficients[i][1][0] = mixer->inputVolume[index].coefficients[(2*i)+1][2*i];
530                    mixerInputSettings.coefficients[i][0][1] = mixer->inputVolume[index].coefficients[2*i][(2*i)+1];
531                    mixerInputSettings.coefficients[i][1][1] = mixer->inputVolume[index].coefficients[(2*i)+1][(2*i)+1];
532                }
533                else
534                {
535                    /* Mute for PCM or compressed inputs is identical */
536                    mixerInputSettings.coefficients[i][0][0] = 0;
537                    mixerInputSettings.coefficients[i][1][0] = 0;
538                    mixerInputSettings.coefficients[i][0][1] = 0;
539                    mixerInputSettings.coefficients[i][1][1] = 0;
540                }
541            }
542            errCode = BAPE_MixerGroup_P_SetInputSettings(mixerGroup, index, &mixerInputSettings);
543            if ( errCode )
544            {
545                return BERR_TRACE(errCode);
546            }
547        }
548    }
549
550    return BERR_SUCCESS;
551}
552
553
554/*************************************************************************/
555static BERR_Code BAPE_StandardMixer_P_SetInputVolume(
556    BAPE_MixerHandle handle,
557    BAPE_Connector input,
558    const BAPE_MixerInputVolume *pVolume
559    )
560{
561    unsigned i;
562    BERR_Code errCode;
563
564    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
565    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
566    BDBG_ASSERT(NULL != pVolume);
567
568    i = BAPE_Mixer_P_FindInputIndex(handle, input);
569    if ( i == BAPE_MIXER_INPUT_INDEX_INVALID )
570    {
571        BDBG_ERR(("Input %p is not connected to mixer %p", input, handle));
572        return BERR_TRACE(BERR_INVALID_PARAMETER);
573    }
574
575    handle->inputVolume[i] = *pVolume;
576    /* Apply volume if input is running */
577    if ( handle->running )
578    {
579        errCode = BAPE_StandardMixer_P_ApplyInputVolume(handle, i);
580        if ( errCode )
581        {
582            return BERR_TRACE(errCode);
583        }
584    }
585
586    return BERR_SUCCESS;   
587}
588
589
590/*************************************************************************/
591static BERR_Code BAPE_StandardMixer_P_ApplyOutputVolume(BAPE_MixerHandle mixer, BAPE_OutputPort output)
592{
593    unsigned i;
594    BERR_Code errCode;
595    BAPE_MixerGroupOutputSettings outputSettings;
596
597    BDBG_ASSERT(mixer == output->mixer);
598    BDBG_ASSERT(NULL != output->sourceMixerGroup);
599
600    BAPE_MixerGroup_P_GetOutputSettings(output->sourceMixerGroup, output->sourceMixerOutputIndex, &outputSettings);
601
602    for ( i = 0; i < BAPE_Channel_eMax; i++ )
603    {
604        outputSettings.coefficients[i] = (mixer->compressed)?BAPE_VOLUME_NORMAL:output->volume.volume[i];
605    }
606
607    if ( output->muteInMixer )
608    {
609        outputSettings.muted = output->volume.muted || (mixer->compressed && mixer->inputMuted[0]);
610        outputSettings.volumeRampDisabled = mixer->compressed;  /* Disable volume ramp if input is compressed for a pseudo-compressed-mute */
611    }
612    else
613    {
614        outputSettings.muted = false;
615        outputSettings.volumeRampDisabled = false;
616    }
617
618    errCode = BAPE_MixerGroup_P_SetOutputSettings(output->sourceMixerGroup ,output->sourceMixerOutputIndex, &outputSettings);
619    if ( errCode )
620    {
621        return BERR_TRACE(errCode);
622    }
623
624    if ( output->setMute )
625    {
626        bool mute = output->volume.muted;
627
628        /* Call the output's mute handler */
629        BDBG_MSG(("Setting output mute to %u", output->volume.muted));
630        output->setMute(output, mute, false);
631    }
632
633    return BERR_SUCCESS;
634}
635
636static bool BAPE_StandardMixer_P_ValidateSettings(const BAPE_MixerSettings *pSettings)
637{
638    switch ( pSettings->defaultSampleRate )
639    {
640    case 32000:
641    case 44100:
642    case 48000:
643        break;
644    default:
645        BDBG_ERR(("Mixers only support default sample rates of 32k, 44.1k or 48kHz."));
646        return false;
647    }
648
649    if ( pSettings->mixerSampleRate )
650    {
651        BDBG_ERR(("Programmable mixer sample rate is not currently supported"));
652        return false;
653    }
654
655    if ( pSettings->outputDelay > BDSP_AF_P_MAX_INDEPENDENT_DELAY )
656    {
657        BDBG_ERR(("Output delay value (%u ms) is larger than the maximum supported (%u ms).", pSettings->outputDelay, BDSP_AF_P_MAX_INDEPENDENT_DELAY));
658        return false;
659    }
660
661    /* Settings are valid */
662    return true;
663}
664
665static BERR_Code BAPE_StandardMixer_P_SetSettings(
666    BAPE_MixerHandle hMixer,
667    const BAPE_MixerSettings *pSettings
668    )
669{
670    bool timebaseChanged;
671
672    BDBG_OBJECT_ASSERT(hMixer, BAPE_Mixer);
673    BDBG_ASSERT(NULL != pSettings);
674
675    if ( hMixer->running )
676    {
677        return BERR_TRACE(BERR_NOT_SUPPORTED);
678    }
679
680    if ( !BAPE_StandardMixer_P_ValidateSettings(pSettings) )
681    {
682        return BERR_TRACE(BERR_INVALID_PARAMETER);
683    }
684   
685    /* Give up our resources if allocated */   
686    BAPE_StandardMixer_P_FreeResources(hMixer);
687
688    /* Determine if the timebase has changed */
689    timebaseChanged = (hMixer->settings.outputTimebase != pSettings->outputTimebase) ? true : false;
690
691    /* Store new settings, they will be applied next time the mixer tries to start */
692    hMixer->settings = *pSettings;
693
694    /* Refresh output timebase if needed */
695    if ( timebaseChanged && hMixer->sampleRate != 0 )
696    {
697        BAPE_OutputPort output;
698
699        BKNI_EnterCriticalSection();
700        for ( output = BLST_S_FIRST(&hMixer->outputList); 
701              output != NULL;
702              output = BLST_S_NEXT(output, node) )
703        {
704            if ( output->setTimingParams_isr )
705            {
706                output->setTimingParams_isr(output, hMixer->sampleRate, pSettings->outputTimebase);
707            }
708        }
709        BKNI_LeaveCriticalSection();
710    }
711
712    return BERR_SUCCESS;
713}
714
715/*************************************************************************/
716/* Allocate mixer resources */
717static BERR_Code BAPE_StandardMixer_P_AllocatePathFromInput(
718    BAPE_PathNode *pNode,
719    BAPE_PathConnection *pConnection
720    )
721{
722    BAPE_MixerHandle handle;
723    BERR_Code errCode;
724
725    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
726   
727    handle = pNode->pHandle;
728    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
729
730    /* Grab mixer-level resources */
731    errCode = BAPE_StandardMixer_P_AllocateResources(handle);
732    if ( errCode )
733    {
734        return BERR_TRACE(errCode);
735    }
736
737    /* Grab resources for this connection */
738    errCode = BAPE_StandardMixer_P_AllocateConnectionResources(handle, pConnection);
739    if ( errCode )
740    {
741        return BERR_TRACE(errCode);
742    }
743
744    return BERR_SUCCESS;
745}
746
747
748/*************************************************************************/
749/* Release mixer resources */
750static void BAPE_StandardMixer_P_FreePathFromInput(
751    BAPE_PathNode *pNode,
752    BAPE_PathConnection *pConnection
753    )
754{
755    BAPE_MixerHandle handle;
756
757    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
758   
759    handle = pNode->pHandle;
760    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
761
762    /* Release resources for this connection */
763    BAPE_StandardMixer_P_FreeConnectionResources(handle, pConnection);
764
765    /* Free mixer-level resources if needed  */
766    BAPE_StandardMixer_P_FreeResources(handle);
767}
768
769
770/*************************************************************************/
771static BERR_Code BAPE_StandardMixer_P_ConfigPathFromInput(
772    struct BAPE_PathNode *pNode, 
773    struct BAPE_PathConnection *pConnection
774    )
775{
776    unsigned inputNum, numChannelPairs;
777    unsigned mixerIndex;
778    BERR_Code errCode;
779   
780    BAPE_MixerHandle handle;
781    BAPE_MixerGroupInputSettings mixerInputSettings;
782
783    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
784
785    handle = pNode->pHandle;
786    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
787   
788    /* Setup linkage from conection into mixer */
789    numChannelPairs = handle->numChannelPairs;
790    inputNum = BAPE_Mixer_P_FindInputIndex(handle, pConnection->pSource);
791
792    for ( mixerIndex = 0; mixerIndex < handle->numMixerGroups; mixerIndex++ )
793    {
794        BAPE_MixerGroupHandle mixerGroup = handle->mixerGroups[mixerIndex];
795        /* Link Input -> Mixer */
796        BAPE_MixerGroup_P_GetInputSettings(mixerGroup, inputNum, &mixerInputSettings);
797        if ( pConnection->srcGroup )
798        {
799            BDBG_MSG(("Linking mixer to associated SRC"));
800            BAPE_SrcGroup_P_GetOutputFciIds(pConnection->srcGroup, &mixerInputSettings.input);
801        }
802        else if ( pConnection->sfifoGroup )
803        {
804            BDBG_MSG(("Linking mixer to associated SFIFO"));
805            BAPE_SfifoGroup_P_GetOutputFciIds(pConnection->sfifoGroup, &mixerInputSettings.input);
806        }
807        else
808        {
809            BDBG_MSG(("Linking mixer to associated FCI"));
810            mixerInputSettings.input = pConnection->inputFciGroup;
811        }
812        errCode = BAPE_MixerGroup_P_SetInputSettings(mixerGroup, inputNum, &mixerInputSettings);
813        if ( errCode )
814        {
815            return BERR_TRACE(errCode);
816        }
817    }
818
819    /* Done.  Refresh input scaling now */
820    BAPE_StandardMixer_P_ApplyInputVolume(handle, inputNum);
821
822    return BERR_SUCCESS;
823}
824
825
826/*************************************************************************/
827static BERR_Code BAPE_StandardMixer_P_StartPathFromInput(
828    struct BAPE_PathNode *pNode, 
829    struct BAPE_PathConnection *pConnection
830    )
831{
832    BAPE_MixerHandle handle;
833    BAPE_Connector input;
834    BAPE_OutputPort output;
835    unsigned mixerIndex, inputIndex;
836    BERR_Code errCode;
837    BAPE_PathConnection *pOutputConnection;
838
839    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
840
841    handle = pNode->pHandle;
842    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
843    input = pConnection->pSource;
844    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
845
846    BDBG_MSG(("Input %s %s starting", input->pParent->pName, input->pName));
847
848    /* First, setup the sample rate since it may affect output programming. */
849    BKNI_EnterCriticalSection();
850    BAPE_StandardMixer_P_InputSampleRateChange_isr(pNode, pConnection);
851    BKNI_LeaveCriticalSection();
852
853    /* Start the global mixer components */
854    if ( handle->running == 0 )
855    {
856        mixerIndex = 0;
857        /* Enable all the mixer outputs */
858        for ( output = BLST_S_FIRST(&handle->outputList); 
859              output != NULL;
860              output = BLST_S_NEXT(output, node) )
861        {
862            BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
863            BDBG_ASSERT(NULL != output->enable);
864
865            BDBG_MSG(("Enabling output %s (%p)", output->pName, output));               
866            errCode = output->enable(output);
867            if ( errCode )
868            {
869                errCode = BERR_TRACE(errCode);
870                goto err_output;
871            }
872
873            /* Apply output volume after enabling outputs (many mute in the output itself) */
874            BAPE_StandardMixer_P_ApplyOutputVolume(handle, output);
875
876            /* Start mixer output(s) */
877            BDBG_ASSERT(NULL != output->sourceMixerGroup);
878            errCode = BAPE_MixerGroup_P_StartOutput(output->sourceMixerGroup, output->sourceMixerOutputIndex);
879            if ( errCode )
880            {
881                errCode = BERR_TRACE(errCode);
882                goto err_output;
883            }
884            /* This had best not fail */
885            BDBG_ASSERT(errCode == BERR_SUCCESS);
886            mixerIndex++;
887        }
888        for ( pOutputConnection = BLST_SQ_FIRST(&handle->pathNode.paths[0].connector.connectionList);
889              pOutputConnection != NULL;
890              pOutputConnection = BLST_SQ_NEXT(pOutputConnection, downstreamNode) )
891        {
892            errCode = BAPE_MixerGroup_P_StartOutput(handle->mixerGroups[mixerIndex], 0);
893            if ( errCode )
894            {
895                errCode = BERR_TRACE(errCode);
896                goto err_output;
897            }
898            mixerIndex++;
899        }
900    }
901
902    /* Enable Mixer Inputs Next */
903    inputIndex = BAPE_Mixer_P_FindInputIndex(handle, input);
904    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
905    for ( mixerIndex = 0; mixerIndex < handle->numMixerGroups; mixerIndex++ )
906    {
907        errCode = BAPE_MixerGroup_P_StartInput(handle->mixerGroups[mixerIndex], inputIndex);
908        if ( errCode )
909        {
910            errCode = BERR_TRACE(errCode);
911            goto err_input;
912        }
913        /* This had best not fail */
914        BDBG_ASSERT(errCode == BERR_SUCCESS);
915    }
916
917    /* Enable SRC's next */
918    if ( pConnection->srcGroup )
919    {
920        errCode = BAPE_SrcGroup_P_Start(pConnection->srcGroup);
921        if ( errCode )
922        {
923            errCode = BERR_TRACE(errCode);
924            goto err_src;
925        }
926    }
927
928    BDBG_MSG(("Mixer Input %s [%u] started", input->pName, inputIndex));
929    handle->running++;
930    handle->inputRunning[inputIndex] = true;
931
932    return BERR_SUCCESS;
933
934err_src:
935    inputIndex = BAPE_Mixer_P_FindInputIndex(handle, input);
936    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
937    for ( mixerIndex = 0; mixerIndex < handle->numMixerGroups; mixerIndex++ )
938    {
939        BAPE_MixerGroup_P_StopInput(handle->mixerGroups[mixerIndex], inputIndex);
940    }   
941err_input:
942err_output:
943    if ( handle->running == 0 )
944    {
945        mixerIndex = 0;
946        /* Disable all the mixer outputs */
947        for ( output = BLST_S_FIRST(&handle->outputList); 
948            output != NULL;
949            output = BLST_S_NEXT(output, node) )
950        {
951            BAPE_MixerGroup_P_StopOutput(output->sourceMixerGroup, output->sourceMixerOutputIndex);
952
953            BDBG_ASSERT(NULL != output->disable);
954            output->disable(output);
955            mixerIndex++;
956        }
957        for ( pOutputConnection = BLST_SQ_FIRST(&handle->pathNode.paths[0].connector.connectionList);
958              pOutputConnection != NULL;
959              pOutputConnection = BLST_SQ_NEXT(pOutputConnection, downstreamNode) )
960        {
961            BAPE_MixerGroup_P_StopOutput(handle->mixerGroups[mixerIndex], 0);
962            mixerIndex++;
963        }
964    }               
965    return errCode;
966}
967
968
969/*************************************************************************/
970static void BAPE_StandardMixer_P_StopPathFromInput(
971    struct BAPE_PathNode *pNode, 
972    struct BAPE_PathConnection *pConnection
973    )
974{
975    BAPE_MixerHandle handle;
976    BAPE_Connector input;
977    BAPE_OutputPort output;
978    unsigned mixerIndex, inputIndex;
979    BAPE_PathConnection *pOutputConnection;
980
981    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
982
983    handle = pNode->pHandle;
984    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
985    input = pConnection->pSource;
986    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
987
988    /* Determine the input index for this connection */
989    inputIndex = BAPE_Mixer_P_FindInputIndex(handle, input);
990    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
991
992    /* If this input was not started (e.g. error in StartPath) return out */
993    if ( !handle->inputRunning[inputIndex] )
994    {
995        BDBG_MSG(("Input %u was not started.  Nothing to stop.", inputIndex));
996        return;
997    }
998    handle->inputRunning[inputIndex] = false;
999
1000    /* Disable SRC */
1001    if ( pConnection->srcGroup )
1002    {
1003        BAPE_SrcGroup_P_Stop(pConnection->srcGroup);
1004    }
1005
1006    /* Disable input to each mixer */
1007    for ( mixerIndex = 0; mixerIndex < handle->numMixerGroups; mixerIndex++ )
1008    {
1009        BAPE_MixerGroup_P_StopInput(handle->mixerGroups[mixerIndex], inputIndex);
1010    }
1011
1012    BDBG_ASSERT(handle->running > 0);
1013    BDBG_MSG(("Mixer run count was %u now %u", handle->running, handle->running-1));
1014    handle->running--;
1015    /* If there are other running inputs, stop outputs here. */
1016    if ( handle->running == 0 )
1017    {
1018        /* We're the last running input.  Stop the mixers and outputs now. */
1019        BDBG_MSG(("Mixer %p (%d) has no more running inputs.  Stopping all mixer outputs.", handle, handle->index));
1020
1021        for ( output = BLST_S_FIRST(&handle->outputList); 
1022            output != NULL;
1023            output = BLST_S_NEXT(output, node) )
1024        {
1025            BDBG_ASSERT(NULL != output->sourceMixerGroup);
1026            BAPE_MixerGroup_P_StopOutput(output->sourceMixerGroup, output->sourceMixerOutputIndex);
1027        }
1028
1029        mixerIndex = 0;
1030        for ( output = BLST_S_FIRST(&handle->outputList); 
1031            output != NULL;
1032            output = BLST_S_NEXT(output, node) )
1033        {
1034            BDBG_MSG(("Disabling output %s (%p)", output->pName, output));
1035
1036            BDBG_ASSERT(NULL != output->disable);
1037            output->disable(output);   
1038            mixerIndex++;
1039        }
1040        for ( pOutputConnection = BLST_SQ_FIRST(&handle->pathNode.paths[0].connector.connectionList);
1041              pOutputConnection != NULL;
1042              pOutputConnection = BLST_SQ_NEXT(pOutputConnection, downstreamNode) )
1043        {
1044            BAPE_MixerGroup_P_StopOutput(handle->mixerGroups[mixerIndex], 0);
1045            mixerIndex++;
1046        }
1047    }   
1048}
1049
1050static BERR_Code BAPE_StandardMixer_P_OutputConnectionAdded(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
1051{
1052    BAPE_MixerHandle handle;
1053
1054    BSTD_UNUSED(pConnection);       
1055    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1056
1057    handle = pNode->pHandle;
1058    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1059   
1060    if ( handle->running > 0 )
1061    {
1062        BDBG_ERR(("Cannot add connections while a mixer is running."));
1063        return BERR_TRACE(BERR_NOT_SUPPORTED);
1064    }
1065   
1066    /* Update number of output connections */
1067    handle->numOutputConnections++;
1068    /* Release any saved resources and re-allocate on the next start call */
1069    BAPE_StandardMixer_P_FreeResources(handle);
1070   
1071    return BERR_SUCCESS;
1072}
1073
1074static void BAPE_StandardMixer_P_OutputConnectionRemoved(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
1075{
1076    BAPE_MixerHandle handle;
1077       
1078    BSTD_UNUSED(pConnection);       
1079    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1080
1081    handle = pNode->pHandle;
1082    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1083
1084    /* Make sure we're not running.  Should never happen. */
1085    BDBG_ASSERT(handle->running == 0);
1086   
1087    /* Release any saved resources and re-allocate on the next start call.  This will also remove any output connection resources. */
1088    BAPE_StandardMixer_P_FreeResources(handle);
1089
1090    /* Decrement number of output connections */
1091    BDBG_ASSERT(handle->numOutputConnections > 0);
1092    handle->numOutputConnections--;       
1093}
1094
1095/*************************************************************************/
1096static void BAPE_StandardMixer_P_InputSampleRateChange_isr(
1097    struct BAPE_PathNode *pNode, 
1098    struct BAPE_PathConnection *pConnection
1099    )
1100{
1101    BAPE_MixerHandle handle;
1102    unsigned sampleRate;
1103
1104    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1105    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1106    BKNI_ASSERT_ISR_CONTEXT();
1107
1108    handle = pNode->pHandle;
1109    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1110
1111    sampleRate = pConnection->pSource->sampleRate;
1112
1113    /* If we are setting the same rate, ignore it */
1114    if ( pConnection->sampleRate == sampleRate && sampleRate != 0 )
1115    {
1116        BDBG_MSG(("Input %s %s sample rate unchanged (%u)", pConnection->pSource->pParent->pName, pConnection->pSource->pName, pConnection->sampleRate));
1117        return;
1118    }
1119
1120    BDBG_MSG(("Input %s %s sample rate changed from %u to %u", pConnection->pSource->pParent->pName, pConnection->pSource->pName, pConnection->sampleRate, sampleRate));
1121
1122    /* Mark new sample rate in connection */
1123    pConnection->sampleRate = sampleRate;
1124
1125    /* Handle the sample rate master */
1126    if ( handle->master == pConnection->pSource )
1127    {
1128        if ( sampleRate != 0 )
1129        {
1130            /* Set mixer sample rate. */
1131            BAPE_StandardMixer_P_SetSampleRate_isr(handle, sampleRate);
1132        }
1133        else if ( handle->sampleRate == 0 )
1134        {
1135            /* Make sure there is a valid sample rate */
1136            BAPE_StandardMixer_P_SetSampleRate_isr(handle, handle->settings.defaultSampleRate);
1137        }
1138    }
1139    else
1140    {
1141        /* Make sure there is a valid sample rate */
1142        if ( handle->sampleRate == 0 )
1143        {
1144            BAPE_StandardMixer_P_SetSampleRate_isr(handle, handle->settings.defaultSampleRate);
1145        }
1146    }
1147
1148    /* Update SRCs accordingly. */
1149    BAPE_StandardMixer_P_SetInputSRC_isr(handle, pConnection->pSource, sampleRate, handle->sampleRate);
1150
1151    if ( pConnection->ppmCorrection )
1152    {
1153        /* Update adaptive rate controllers */
1154        BAPE_SfifoGroup_P_SetSampleRate_isr(pConnection->sfifoGroup, sampleRate);
1155    }
1156}
1157
1158
1159/*************************************************************************/
1160static BERR_Code BAPE_StandardMixer_P_InputFormatChange(
1161    struct BAPE_PathNode *pNode, 
1162    struct BAPE_PathConnection *pConnection
1163    )
1164{
1165    BAPE_MixerHandle handle;
1166
1167    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1168    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1169
1170    handle = pNode->pHandle;
1171    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1172
1173    /* Handle a format change by releasing all connection resources.
1174       They will get re-allocated on the next start sequence for the correct format.
1175    */
1176    BAPE_StandardMixer_P_FreeConnectionResources(handle, pConnection);
1177   
1178    /* Need to re-allocate mixer resources for some changes (but not all).  Check those cases here. */
1179    if ( pConnection->pSource->compressed != handle->compressed )
1180    {
1181        if ( handle->running > 0 )
1182        {
1183            /* Can't free mixer resources while running */
1184            BDBG_ERR(("Can not change from compressed to PCM or vice-versa while other inputs are running."));
1185            return BERR_TRACE(BERR_NOT_SUPPORTED);
1186        }
1187        /* Mixer compressed state will be set when first input starts */
1188        BAPE_StandardMixer_P_FreeResources(handle);
1189    }
1190    if ( pConnection->pSource->numChannelPairs > handle->numChannelPairs )
1191    {
1192        if ( handle->running > 0 )
1193        {
1194            BDBG_ERR(("Input is wider than the current mixer data format.  Cannot change this while other inputs are running."));
1195            return BERR_TRACE(BERR_NOT_SUPPORTED);
1196        }
1197        /* Mixer output format will be set when first input starts */
1198        BAPE_StandardMixer_P_FreeResources(handle);
1199    }
1200
1201    handle->pathNode.paths[0].connector.codec = pConnection->pSource->codec;
1202
1203    return BERR_SUCCESS;
1204}
1205
1206
1207/*************************************************************************/
1208static void BAPE_StandardMixer_P_InputMute(
1209    struct BAPE_PathNode *pNode, 
1210    struct BAPE_PathConnection *pConnection,
1211    bool enabled
1212    )
1213{
1214    BAPE_MixerHandle handle;
1215    unsigned i;
1216
1217    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1218    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1219
1220    handle = pNode->pHandle;
1221    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1222
1223    /* Determine mixer input index */
1224    i = BAPE_Mixer_P_FindInputIndex(handle, pConnection->pSource);
1225
1226    /* Should never happen */
1227    BDBG_ASSERT(i < BAPE_CHIP_MAX_MIXER_INPUTS);
1228
1229    /* See if mute state is changing */
1230    if ( handle->inputMuted[i] != enabled )
1231    {
1232        /* Update mute state and re-apply input volume */
1233        handle->inputMuted[i] = enabled;
1234        BAPE_StandardMixer_P_ApplyInputVolume(handle, i);
1235    }
1236}
1237
1238
1239/*************************************************************************/
1240static BERR_Code BAPE_StandardMixer_P_ConnectorSupported(
1241    struct BAPE_PathNode *pNode, 
1242    BAPE_PathConnector *pConnector
1243    )
1244{
1245    BAPE_MixerHandle handle;
1246    unsigned i;
1247
1248    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1249    BDBG_OBJECT_ASSERT(pConnector, BAPE_PathConnector);
1250
1251    handle = pNode->pHandle;
1252    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1253   
1254    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
1255    {
1256        if ( handle->inputs[i] != NULL && handle->inputs[i] != pConnector )
1257        {
1258            /* We can't mix compressed and un-compressed inputs.  Validate that here. */
1259            if ( handle->inputs[i]->compressed != pConnector->compressed )
1260            {
1261                BDBG_ERR(("You can not mix compressed and un-compressed inputs."));
1262                return BERR_TRACE(BERR_NOT_SUPPORTED);
1263            }
1264        }
1265    }
1266
1267    return BERR_SUCCESS;
1268}
1269
1270
1271/*************************************************************************/
1272static BAPE_MclkSource BAPE_StandardMixer_P_GetMclkSource(BAPE_MixerHandle mixer)
1273{
1274    BAPE_OutputPort output;
1275    bool needMclk = false;
1276    bool pllRequired = false;
1277    bool ncoRequired = false;
1278    BAPE_MixerHandle thisMixer;
1279
1280    /* Do we even need an MCLK source? */
1281    BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Beginning MCLK selection", mixer ));
1282
1283    for ( output = BLST_S_FIRST(&mixer->outputList);
1284          output != NULL;
1285          output = BLST_S_NEXT(output, node) )
1286    {
1287        BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
1288        if ( output->setMclk_isr || output->fsTiming )
1289        {
1290            needMclk = true;
1291            break;
1292        }
1293    }
1294
1295    if ( false == needMclk )
1296    {
1297        /* No outputs need MCLK (all are DACs) */
1298        BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Done (no outputs need MCLK) Returning %s",
1299                                                     mixer, BAPE_Mixer_P_MclkSourceToText(BAPE_MclkSource_eNone )));
1300        return BAPE_MclkSource_eNone;
1301    }
1302
1303    /* Check local outputs first */
1304    for ( output = BLST_S_FIRST(&mixer->outputList);
1305          output != NULL;
1306          output = BLST_S_NEXT(output, node) )
1307    {
1308        BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
1309        if ( output->mclkOutput != BAPE_MclkSource_eNone )
1310        {
1311            BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Done (output provides MCLK) Returning %s",
1312                                                         mixer, BAPE_Mixer_P_MclkSourceToText(output->mclkOutput) ));
1313            return output->mclkOutput;  /* the mixer has a DAC output, use the DAC's rate manager */
1314        }
1315        if ( output->pllRequired )
1316        {
1317            pllRequired = true;
1318        }
1319        if ( output->builtinNco )
1320        {
1321            ncoRequired = true;
1322        }
1323    }
1324
1325    /* At this point, the mixer has no outputs generating a usable clock source,
1326     * now see if there are any outputs that request a PLL (like Spdif or I2S), if so,
1327     * then try use the PLL specified in settings.outputPll.  If we have an output that
1328     * requires an NCO (e.g. DAC on 7429) then skip this.
1329     */
1330    if ( ncoRequired )
1331    {
1332        BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Outputs require an NCO clock", mixer ));
1333    }
1334    else if ( pllRequired )
1335    {
1336        BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Outputs desire a PLL clock", mixer ));
1337        /* If the outputPll mixer setting is valid, use it. */
1338        if ( (signed)mixer->settings.outputPll >= BAPE_Pll_e0 && mixer->settings.outputPll < BAPE_Pll_eMax )
1339        {
1340            unsigned pllIndex = mixer->settings.outputPll - BAPE_Pll_e0;
1341            if ( pllIndex < BAPE_CHIP_MAX_PLLS )
1342            {
1343                BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Done (valid PLL specified) Returning %s", mixer, BAPE_Mixer_P_MclkSourceToText(pllIndex + BAPE_MclkSource_ePll0)));
1344                return pllIndex + BAPE_MclkSource_ePll0;
1345            }
1346        }
1347        BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Valid PLL was not specified, continuing...", mixer ));
1348    }
1349
1350    /* Now use an NCO if one was specified. */
1351    #if BAPE_CHIP_MAX_NCOS > 0
1352        if ( (signed)mixer->settings.outputNco >= BAPE_Nco_e0 && mixer->settings.outputNco < BAPE_Nco_eMax )
1353        {
1354            unsigned ncoIndex = mixer->settings.outputNco - BAPE_Nco_e0;
1355            if ( ncoIndex < BAPE_CHIP_MAX_NCOS )
1356            {
1357                BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Done (valid NCO specified) Returning %s", mixer, BAPE_Mixer_P_MclkSourceToText(ncoIndex + BAPE_MclkSource_eNco0) ));
1358                return ncoIndex + BAPE_MclkSource_eNco0;
1359            }
1360        }
1361    #endif /* BAPE_CHIP_MAX_NCOS */
1362
1363    if ( ncoRequired )
1364    {
1365        BDBG_ERR(("Mixer %p requires an NCO but one has not been specified.", mixer));
1366        return BAPE_MclkSource_eMax;
1367    }
1368    else
1369    {
1370        BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Valid NCO was not specified, continuing...", mixer ));
1371    }
1372
1373    BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Peeking for DAC on another mixer", mixer ));
1374    /* Check all open mixers with matching inputs and settings  */
1375    for ( thisMixer = BLST_S_FIRST(&mixer->deviceHandle->mixerList);
1376          thisMixer != NULL;
1377          thisMixer = BLST_S_NEXT(thisMixer, node) )
1378    {
1379        int i, j;
1380        bool matchInput=true, matchSettings=false;
1381
1382        if ( thisMixer == mixer )
1383        {
1384            continue;
1385        }
1386
1387        /* Determine if we have a matching timing or not */
1388        if ( mixer->master )
1389        {
1390            /* Must have the same master channel, timebase, and default sample rate */
1391            if ( thisMixer->master && 
1392                 (thisMixer->master->pParent == mixer->master->pParent) &&
1393                 (thisMixer->settings.outputTimebase == mixer->settings.outputTimebase) &&
1394                 (thisMixer->settings.defaultSampleRate == thisMixer->settings.defaultSampleRate) )
1395            {
1396                matchSettings = true;
1397            }
1398        }
1399        else
1400        {
1401            /* No master, just default timing. */
1402            if ( NULL == thisMixer->master &&
1403                 (thisMixer->settings.outputTimebase == mixer->settings.outputTimebase) &&
1404                 (thisMixer->settings.defaultSampleRate == mixer->settings.defaultSampleRate) )
1405            {
1406                matchSettings = true;
1407            }
1408        }
1409
1410        /* Must match all inputs */
1411        for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
1412        {
1413            if ( mixer->inputs[i] )
1414            {
1415                for ( j = 0; j < BAPE_CHIP_MAX_MIXER_INPUTS; j++ )
1416                {
1417                    if ( thisMixer->inputs[j] &&
1418                         (thisMixer->inputs[j]->pParent == mixer->inputs[i]->pParent) )
1419                    {
1420                        break;
1421                    }
1422                }
1423                if ( j >= BAPE_CHIP_MAX_MIXER_INPUTS )
1424                {
1425                    matchInput = false;
1426                    break;
1427                }
1428            }
1429            if ( thisMixer->inputs[i] )
1430            {
1431                for ( j = 0; j < BAPE_CHIP_MAX_MIXER_INPUTS; j++ )
1432                {
1433                    if ( mixer->inputs[j] &&
1434                         (mixer->inputs[j]->pParent == thisMixer->inputs[i]->pParent) )
1435                    {
1436                        break;
1437                    }
1438                }
1439                if ( j >= BAPE_CHIP_MAX_MIXER_INPUTS )
1440                {
1441                    matchInput = false;
1442                    break;
1443                }
1444            }
1445        }
1446
1447        /* If we've matched settings and input(s), look for an mclk source */
1448        if ( matchSettings && matchInput )
1449        {
1450            for ( output = BLST_S_FIRST(&thisMixer->outputList);
1451                  output != NULL;
1452                  output = BLST_S_NEXT(output, node) )
1453            {
1454                BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
1455                if ( output->mclkOutput != BAPE_MclkSource_eNone )
1456                {
1457                    BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p (Found a DAC RM on another mixer) Returning %s", 
1458                                                                 mixer, BAPE_Mixer_P_MclkSourceToText(output->mclkOutput)));
1459                    BDBG_MSG(("Found associated MCLK source %s", BAPE_Mixer_P_MclkSourceToText(output->mclkOutput)));
1460                    return output->mclkOutput;
1461                }
1462            }
1463        }
1464    }
1465    BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Couldn't find usable DAC on another mixer", mixer ));
1466
1467
1468    /* If we get here, we haven't found one.  Return the PLL if
1469     * one was specified, otherwise just fail.
1470     */
1471    if ( (signed)mixer->settings.outputPll >= BAPE_Pll_e0 && mixer->settings.outputPll < BAPE_Pll_eMax )
1472    {
1473        unsigned pllIndex = mixer->settings.outputPll - BAPE_Pll_e0;
1474        if ( pllIndex < BAPE_CHIP_MAX_PLLS )
1475        {
1476            BDBG_MODULE_MSG(bape_mixer_get_mclk_source, ("Mixer:%p Done (last resort, using specified PLL) Returning %s", mixer, BAPE_Mixer_P_MclkSourceToText(pllIndex + BAPE_MclkSource_ePll0)));
1477            return pllIndex + BAPE_MclkSource_ePll0;
1478        }
1479    }
1480
1481    BDBG_ERR(("Can't find MCLK source for mixer:%p, giving up.", mixer ));
1482   
1483    return BERR_TRACE(BAPE_MclkSource_eMax);    /* this indicates failure */
1484}
1485
1486
1487/*************************************************************************/
1488static BERR_Code BAPE_StandardMixer_P_AllocateResources(BAPE_MixerHandle mixer)
1489{
1490    unsigned i,j;
1491    BAPE_OutputPort output;
1492    BAPE_MclkSource mclkSource;
1493    unsigned numChannelPairs=0;
1494    unsigned numOutputs=0;
1495    bool compressed = false;
1496    bool fsRequired = false;
1497    BERR_Code errCode=BERR_SUCCESS;
1498    BAPE_PathConnection *pConnection;
1499
1500    BDBG_OBJECT_ASSERT(mixer, BAPE_Mixer);
1501
1502    if ( mixer->ready )
1503    {
1504        BDBG_MSG(("Mixer %p (%d) already has resources allocated", mixer, mixer->index));
1505        return BERR_SUCCESS;
1506    }
1507
1508    output = BLST_S_FIRST(&mixer->outputList);
1509    if ( NULL == output && 0 == mixer->numOutputConnections )
1510    {
1511        BDBG_ERR(("No outputs or nodes connected to mixer %p (%d), cannot allocate resources.", mixer, mixer->index));
1512        return BERR_TRACE(BERR_NOT_SUPPORTED);
1513    }
1514
1515    /* First determine number of channel pairs required */
1516    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
1517    {
1518        if ( mixer->inputs[i] )
1519        {
1520            j = mixer->inputs[i]->numChannelPairs;
1521            if ( numChannelPairs == 0 && mixer->inputs[i]->compressed )
1522            {
1523                compressed = true;
1524            }
1525            else if ( compressed && !mixer->inputs[i]->compressed )
1526            {
1527                BDBG_ERR(("Cannot mix compressed and uncompressed data.  Unable to start mixer %p (%d)", mixer, mixer->index));
1528                return BERR_TRACE(BERR_NOT_SUPPORTED);
1529            }
1530            if ( j > numChannelPairs )
1531            {
1532                numChannelPairs = j;
1533            }
1534        }
1535    }
1536
1537    /* Make sure we actually found something worthwhile */
1538    if ( numChannelPairs == 0 )
1539    {
1540        BDBG_ERR(("No input data for mixer %p (%d).  Cannot allocate resources.", mixer, mixer->index));
1541        return BERR_TRACE(BERR_INVALID_PARAMETER);
1542    }
1543
1544    /* Make sure all outputs are capable of receiving this data format */
1545    for ( output = BLST_S_FIRST(&mixer->outputList);
1546          output != NULL;
1547          output = BLST_S_NEXT(output, node) )
1548    {
1549        BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
1550        if ( output->maxChannelPairs < numChannelPairs )
1551        {
1552            BDBG_ERR(("Mixer %p (%d) cannot route %d channel pairs to output %p.  Cannot start.", mixer, mixer->index, numChannelPairs, output));
1553            return BERR_TRACE(BERR_NOT_SUPPORTED);
1554        }
1555        numOutputs++;
1556    }
1557
1558    if ( numChannelPairs != mixer->pathNode.paths[0].connector.numChannelPairs ||
1559         compressed != mixer->pathNode.paths[0].connector.compressed )
1560    {
1561        mixer->pathNode.paths[0].connector.numChannelPairs = numChannelPairs;
1562        mixer->pathNode.paths[0].connector.compressed = compressed;
1563        errCode = BAPE_Connector_P_FormatChange(&mixer->pathNode.paths[0].connector);
1564        if ( errCode )
1565        {
1566            return BERR_TRACE(errCode);
1567        }
1568    }
1569   
1570    mixer->numChannelPairs = numChannelPairs;
1571    mixer->compressed = compressed;
1572
1573    BDBG_MSG(("Mixer %p (%d): Allocating mixers for %u outputs with %u channel pairs.", 
1574              mixer, mixer->index, numOutputs*numChannelPairs, numOutputs, numChannelPairs));
1575
1576    /* This allocates the required number of mixers */
1577    errCode = BAPE_StandardMixer_P_AllocateMixerGroups(mixer);
1578    if ( errCode )
1579    {
1580        BDBG_ERR(("Unable to allocate %u hardware mixers.  Please reduce the number of outputs and/or the number of output channels.", numOutputs * numChannelPairs));
1581        errCode = BERR_TRACE(errCode);
1582        goto err_mixers;
1583    }
1584   
1585    /* Now, we have the resources we need.  Setup the linkage correctly. */   
1586    i=0;
1587    for ( output = BLST_S_FIRST(&mixer->outputList);
1588          output != NULL;
1589          output = BLST_S_NEXT(output, node) )
1590    {
1591        /* First output always to master */
1592        output->sourceMixerGroup = mixer->mixerGroups[i];
1593        output->sourceMixerOutputIndex = 0;
1594        BAPE_MixerGroup_P_GetOutputFciIds(mixer->mixerGroups[i], 0, &output->sourceMixerFci);
1595
1596        i++;
1597    }
1598   
1599    /* Setup Downstream connections as well */
1600    for ( pConnection = BLST_SQ_FIRST(&mixer->pathNode.paths[0].connector.connectionList);
1601          pConnection != NULL;
1602          pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
1603    {
1604        BAPE_MixerGroup_P_GetOutputFciIds(mixer->mixerGroups[i], 0, &pConnection->inputFciGroup);
1605        i++;
1606    }
1607   
1608    /* Refresh output scaling */   
1609    for ( output = BLST_S_FIRST(&mixer->outputList);
1610          output != NULL;
1611          output = BLST_S_NEXT(output, node) )
1612    {
1613        BDBG_MSG(("Refreshing output scaling for output %p", output));
1614        BAPE_StandardMixer_P_ApplyOutputVolume(mixer, output);
1615    }
1616   
1617    mclkSource = BAPE_StandardMixer_P_GetMclkSource(mixer);
1618    if ( mclkSource >= BAPE_MclkSource_eMax )
1619    {
1620        BDBG_ERR(("Unable to find MclkSource for mixer."));
1621        errCode = BERR_TRACE(BERR_NOT_SUPPORTED);
1622        goto err_mixer_mclksource;
1623    }
1624
1625    mixer->mclkSource = mclkSource;
1626    if (BAPE_MCLKSOURCE_IS_PLL(mclkSource))
1627    {
1628        #if BAPE_CHIP_MAX_PLLS > 0
1629        BAPE_P_AttachMixerToPll(mixer, mixer->mclkSource - BAPE_MclkSource_ePll0);
1630        #endif
1631    }
1632    else if (BAPE_MCLKSOURCE_IS_NCO(mclkSource))
1633    {
1634        #if BAPE_CHIP_MAX_NCOS > 0
1635            BAPE_P_AttachMixerToNco(mixer, mixer->mclkSource - BAPE_MclkSource_eNco0);
1636        #endif
1637    }
1638    else  /* Must be a DAC or none. */
1639    {
1640        BKNI_EnterCriticalSection();
1641        /* Set outputs to DAC rate manager MCLK if required */
1642        for ( output = BLST_S_FIRST(&mixer->outputList);
1643              output != NULL;
1644              output = BLST_S_NEXT(output, node) )
1645        {
1646            if ( output->setMclk_isr )
1647            {
1648                output->setMclk_isr(output, mixer->mclkSource, 0, 256 /* DAC is 256*Fs */); /* Actually, at Fs > 48 KHz the DAC runs at 64*Fs */
1649            }
1650        }
1651        BKNI_LeaveCriticalSection();
1652    }
1653
1654    /* Determine if we need an Fs or not */
1655    for ( output = BLST_S_FIRST(&mixer->outputList);
1656          output != NULL;
1657          output = BLST_S_NEXT(output, node) )
1658    {
1659        if ( output->fsTiming )
1660        {
1661            fsRequired = true;
1662            break;
1663        }
1664    }
1665
1666    /* Try and grab an Fs */
1667    if ( fsRequired )
1668    {
1669        mixer->fs = BAPE_P_AllocateFs(mixer->deviceHandle);
1670        if ( mixer->fs == BAPE_FS_INVALID )
1671        {
1672            BDBG_ERR(("Unable to allocate fs timing source"));
1673            errCode = BERR_TRACE(BERR_NOT_SUPPORTED);
1674            goto err_alloc_fs;
1675        }
1676        if ( BAPE_MCLKSOURCE_IS_PLL(mclkSource))
1677        {
1678            /* Do nothing.  The PLL set freq will set the fs timing. */
1679        }
1680        else if ( BAPE_MCLKSOURCE_IS_NCO(mclkSource))
1681        {
1682            /* Do nothing.  The NCO set freq will set the fs timing. */
1683        }
1684        else
1685        {
1686            /* Set the FS to use DAC timing */
1687            BKNI_EnterCriticalSection();
1688            BAPE_P_SetFsTiming_isr(mixer->deviceHandle, 
1689                                   mixer->fs, 
1690                                   mixer->mclkSource, 
1691                                   0,       /* pllChan doesn't apply */
1692                                   256 );   /* DAC is 256Fs */
1693            BKNI_LeaveCriticalSection();
1694        }   
1695        /* Bind each output to the fs */     
1696        for ( output = BLST_S_FIRST(&mixer->outputList);
1697              output != NULL;
1698              output = BLST_S_NEXT(output, node) )
1699        {
1700            if ( output->fsTiming )
1701            {
1702                BDBG_ASSERT(NULL != output->setFs);
1703                output->setFs(output, mixer->fs);
1704            }
1705        }
1706    }
1707
1708    mixer->ready = true;
1709    return BERR_SUCCESS;
1710
1711err_alloc_fs:
1712    if ( mixer->fs != BAPE_FS_INVALID )
1713    {
1714        BAPE_P_FreeFs(mixer->deviceHandle, mixer->fs);
1715        mixer->fs = BAPE_FS_INVALID;
1716    }
1717
1718err_mixer_mclksource:
1719    BAPE_StandardMixer_P_FreeResources(mixer);
1720   
1721err_mixers:
1722    return errCode;
1723}
1724
1725/*************************************************************************/
1726static void BAPE_StandardMixer_P_SetSampleRate_isr(BAPE_MixerHandle mixer, unsigned sampleRate)
1727{
1728    BDBG_OBJECT_ASSERT(mixer, BAPE_Mixer);
1729    /* Only do this if something actually changed */
1730    if ( mixer->sampleRate != sampleRate )
1731    {
1732        unsigned i;
1733        BAPE_OutputPort output;
1734
1735        BDBG_MSG(("Changing mixer %p (%d) sample rate to %u [was %u]", mixer, mixer->index, sampleRate, mixer->sampleRate));
1736        mixer->sampleRate = sampleRate;
1737        for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
1738        {
1739            if ( mixer->inputs[i] )
1740            {
1741                BAPE_StandardMixer_P_SetInputSRC_isr(mixer, mixer->inputs[i], mixer->inputs[i]->sampleRate, sampleRate);
1742            }
1743        }
1744
1745        /* For each output... */
1746        for ( output = BLST_S_FIRST(&mixer->outputList);
1747              output != NULL;
1748              output = BLST_S_NEXT(output, node) )
1749        {
1750            if ( output->setTimingParams_isr )
1751            {
1752                output->setTimingParams_isr(output, sampleRate, mixer->settings.outputTimebase);
1753            }
1754        }
1755
1756        #if BAPE_CHIP_MAX_PLLS > 0
1757        if ( BAPE_MCLKSOURCE_IS_PLL(mixer->mclkSource) && sampleRate != 0 )
1758        {
1759            BERR_Code errCode;
1760            /* Update the PLL */
1761            errCode = BAPE_P_UpdatePll_isr(mixer->deviceHandle, mixer->settings.outputPll);
1762            BDBG_ASSERT(errCode == BERR_SUCCESS);
1763        }
1764        #endif
1765
1766        #if BAPE_CHIP_MAX_NCOS > 0
1767        if ( BAPE_MCLKSOURCE_IS_NCO(mixer->mclkSource) && sampleRate != 0 )
1768        {
1769            BERR_Code errCode;
1770            /* Update the NCO */
1771            errCode = BAPE_P_UpdateNco_isr(mixer->deviceHandle, mixer->settings.outputNco);
1772            BDBG_ASSERT(errCode == BERR_SUCCESS);
1773        }
1774        #endif
1775
1776        if ( sampleRate != 0 )
1777        {           
1778            /* Propagate sample rate downstream */
1779            mixer->pathNode.paths[0].connector.sampleRate = sampleRate;
1780            BAPE_Connector_P_SampleRateChange_isr(&mixer->pathNode.paths[0].connector);
1781        }
1782    }
1783    else
1784    {
1785        BDBG_MSG(("NOT Changing mixer %p (%d) sample rate to %u [currently %u]", mixer, mixer->index, sampleRate, mixer->sampleRate));
1786    }
1787}
1788
1789/*************************************************************************/
1790static void BAPE_StandardMixer_P_SetInputSRC_isr(BAPE_MixerHandle mixer, BAPE_Connector input, unsigned inputRate, unsigned outputRate)
1791{
1792    BAPE_PathConnection *pLink=NULL;
1793
1794    BDBG_OBJECT_ASSERT(mixer, BAPE_Mixer);
1795    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
1796
1797    /* Find connection node for this object */
1798    for ( pLink = BLST_SQ_FIRST(&input->connectionList);
1799          NULL != pLink;
1800          pLink = BLST_SQ_NEXT(pLink, downstreamNode) )
1801    {
1802        if ( pLink->pSink == &mixer->pathNode )
1803            break;
1804    }
1805    BDBG_ASSERT(NULL != pLink);
1806
1807    if ( pLink->srcGroup )
1808    {
1809        BDBG_MSG(("Setting input %s SRC to %u->%u", input->pName, inputRate, outputRate));
1810        BAPE_SrcGroup_P_SetSampleRate_isr(pLink->srcGroup, inputRate, outputRate);
1811    }
1812}
1813
1814
1815/*************************************************************************/
1816static BERR_Code BAPE_StandardMixer_P_AllocateConnectionResources(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection)
1817{
1818    BERR_Code errCode;
1819    bool sfifoRequired=false, srcRequired=false, buffersOnly=false;
1820
1821    BAPE_Connector input = pConnection->pSource;
1822
1823    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1824    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1825    BDBG_ASSERT(&handle->pathNode == pConnection->pSink);
1826
1827    switch ( pConnection->pSource->dataSource )
1828    {
1829    case BAPE_DataSource_eDfifo:
1830    case BAPE_DataSource_eDspBuffer:
1831    case BAPE_DataSource_eHostBuffer:
1832        /* SFIFO is required - also always allocate SRC since it handles startup ramp and input mute */
1833        sfifoRequired = true;
1834        srcRequired = true;         /* TODO: Possibly omit for compressed sources */
1835        break;
1836    case BAPE_DataSource_eFci:         
1837        /* TODO: Many cases could require an SRC - omit now to save HW resources for EQ */
1838        return BERR_SUCCESS;
1839    default:
1840        BDBG_ERR(("Unrecognized source type %u", pConnection->pSource->dataSource));
1841        return BERR_TRACE(BERR_NOT_SUPPORTED);
1842    }
1843   
1844    BDBG_MSG(("Mixer %p Allocating resources for input %s %s", handle, input->pParent->pName, input->pName));
1845
1846    /* Check if we've already allocated resources */
1847    if ( pConnection->numChannelPairs > 0 )
1848    {
1849        if ( (pConnection->numChannelPairs == input->numChannelPairs) && (input->compressed == pConnection->compressed) &&
1850             (pConnection->ppmCorrection == pConnection->pSource->ppmCorrection) )
1851        {
1852            BDBG_MSG(("Connection %s -> %s %s already has the required resources", input->pParent->pName, pConnection->pSink->pName, input->pName));
1853            if ( sfifoRequired )
1854            {
1855                BDBG_ASSERT(NULL != pConnection->sfifoGroup);
1856            }
1857            if ( srcRequired )
1858            {
1859                BDBG_ASSERT(NULL != pConnection->srcGroup);
1860            }
1861
1862            buffersOnly = true;
1863        }
1864        else
1865        {
1866            /* Connection format has changed */
1867            BDBG_MSG(("Connection %s -> %s %s format changed.  Releasing resources.", input->pParent->pName, pConnection->pSink->pName, input->pName));
1868            BAPE_StandardMixer_P_FreeConnectionResources(handle, pConnection);
1869        }
1870    }
1871
1872    if ( input->useBufferPool )
1873    {
1874        /* This is safe to call multiple times, it only allocates if need be */
1875        errCode = BAPE_P_AllocateInputBuffers(handle->deviceHandle, input);
1876        if ( errCode )
1877        {
1878            return BERR_TRACE(errCode);
1879        }
1880    }
1881
1882    if ( buffersOnly )
1883    {
1884        /* We don't need to re-add the remaining resources */
1885        return BERR_SUCCESS;
1886    }
1887
1888    pConnection->numChannelPairs = 0;
1889    pConnection->compressed = false;
1890    pConnection->ppmCorrection = false;
1891
1892    BDBG_ASSERT(NULL == pConnection->sfifoGroup);
1893    BDBG_ASSERT(NULL == pConnection->srcGroup);
1894
1895    if ( sfifoRequired )
1896    {
1897        BAPE_SfifoGroupCreateSettings sfifoCreateSettings;
1898        BAPE_SfifoGroup_P_GetDefaultCreateSettings(&sfifoCreateSettings);
1899        sfifoCreateSettings.numChannelPairs = pConnection->pSource->numChannelPairs;
1900        sfifoCreateSettings.ppmCorrection = pConnection->pSource->ppmCorrection;
1901        errCode = BAPE_SfifoGroup_P_Create(handle->deviceHandle, &sfifoCreateSettings, &pConnection->sfifoGroup);
1902        if ( errCode )
1903        {
1904            (void)BERR_TRACE(errCode);
1905            goto err_alloc_sfifo;
1906        }
1907    }
1908
1909    if ( srcRequired )
1910    {
1911        BAPE_SrcGroupSettings srcSettings;
1912        BAPE_SrcGroupCreateSettings srcCreateSettings;
1913        BAPE_SrcGroup_P_GetDefaultCreateSettings(&srcCreateSettings);
1914        srcCreateSettings.numChannelPairs = pConnection->pSource->numChannelPairs;
1915        errCode = BAPE_SrcGroup_P_Create(handle->deviceHandle, &srcCreateSettings, &pConnection->srcGroup);
1916        if ( errCode )
1917        {
1918            (void)BERR_TRACE(errCode);
1919            goto err_alloc_src;
1920        }
1921        /* Set SRC Linkage */
1922        BAPE_SrcGroup_P_GetSettings(pConnection->srcGroup, &srcSettings);
1923        if ( pConnection->sfifoGroup )
1924        {
1925            /* Input From Sfifo */
1926            BAPE_SfifoGroup_P_GetOutputFciIds(pConnection->sfifoGroup, &srcSettings.input);
1927        }
1928        else
1929        {
1930            /* Input from other FCI source */
1931            srcSettings.input = pConnection->inputFciGroup;
1932        }
1933        srcSettings.rampEnabled = !handle->compressed;
1934        srcSettings.startupRampEnabled = !handle->compressed;
1935        errCode = BAPE_SrcGroup_P_SetSettings(pConnection->srcGroup, &srcSettings);
1936        if ( errCode )
1937        {
1938            errCode = BERR_TRACE(errCode);
1939            goto err_src_settings;
1940        }
1941    }
1942
1943    pConnection->numChannelPairs = pConnection->pSource->numChannelPairs;
1944    pConnection->compressed = pConnection->pSource->compressed;
1945    pConnection->ppmCorrection = pConnection->pSource->ppmCorrection;
1946
1947    return BERR_SUCCESS;
1948
1949    err_src_settings:
1950    if ( pConnection->srcGroup )
1951    {
1952        BAPE_SrcGroup_P_Destroy(pConnection->srcGroup);
1953        pConnection->srcGroup = NULL;
1954    }
1955    err_alloc_src:
1956    if ( pConnection->sfifoGroup )
1957    {
1958        BAPE_SfifoGroup_P_Destroy(pConnection->sfifoGroup);
1959        pConnection->sfifoGroup = NULL;
1960    }
1961    err_alloc_sfifo:
1962    BAPE_P_FreeInputBuffers(handle->deviceHandle, pConnection->pSource);
1963    return errCode;
1964}
1965
1966/*************************************************************************/
1967static void BAPE_StandardMixer_P_FreeConnectionResources(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection)
1968{
1969    if ( pConnection->pSource->useBufferPool )
1970    {
1971        BAPE_P_FreeInputBuffers(handle->deviceHandle, pConnection->pSource);
1972    }
1973    if ( pConnection->srcGroup )
1974    {
1975        BAPE_SrcGroup_P_Destroy(pConnection->srcGroup);
1976        pConnection->srcGroup = NULL;
1977    }
1978    if ( pConnection->sfifoGroup )
1979    {
1980        BAPE_SfifoGroup_P_Destroy(pConnection->sfifoGroup);
1981        pConnection->sfifoGroup = NULL;
1982    }
1983    pConnection->numChannelPairs = 0;       /* Required to force allocations next time */
1984    pConnection->ppmCorrection = false;
1985    pConnection->sampleRate = 0;   
1986}
1987
1988/*************************************************************************/
1989static void BAPE_StandardMixer_P_FreeResources(BAPE_MixerHandle handle)
1990{
1991    unsigned i;
1992    BAPE_PathConnection *pConnection;
1993
1994    BDBG_MSG(("Mixer %d (%#x) Free Resources", handle->index, handle));
1995
1996    if ( handle->running )
1997    {
1998        BDBG_ERR(("Can't release resources while mixer %p (%d) is running", handle, handle->index));
1999        BDBG_ASSERT(!handle->running);
2000        return;
2001    }
2002
2003    if ( !handle->ready )
2004    {
2005        /* Nothing to do */
2006        return;
2007    }
2008
2009#if BAPE_CHIP_MAX_PLLS > 0
2010    if ( BAPE_MCLKSOURCE_IS_PLL(handle->mclkSource))
2011    {
2012        BAPE_P_DetachMixerFromPll(handle, handle->mclkSource - BAPE_MclkSource_ePll0);
2013    }
2014#endif
2015
2016#if BAPE_CHIP_MAX_NCOS > 0
2017    if ( BAPE_MCLKSOURCE_IS_NCO(handle->mclkSource))
2018    {
2019        BAPE_P_DetachMixerFromNco(handle, handle->mclkSource - BAPE_MclkSource_eNco0);
2020    }
2021#endif
2022        handle->mclkSource = BAPE_MclkSource_eNone;
2023
2024    if ( handle->fs != BAPE_FS_INVALID )
2025    {
2026        BAPE_P_FreeFs(handle->deviceHandle, handle->fs);
2027        handle->fs = BAPE_FS_INVALID;
2028    }
2029
2030    /* Invalidate Downstream connections as well */
2031    for ( pConnection = BLST_SQ_FIRST(&handle->pathNode.paths[0].connector.connectionList);
2032          pConnection != NULL;
2033          pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
2034    {
2035        BAPE_FciIdGroup_Init(&pConnection->inputFciGroup);
2036    }
2037
2038    for ( i = 0; i < handle->numMixerGroups; i++ )
2039    {
2040        BDBG_ASSERT(NULL != handle->mixerGroups[i]);
2041        BAPE_MixerGroup_P_Destroy(handle->mixerGroups[i]);
2042        handle->mixerGroups[i] = NULL;
2043    }
2044    handle->numMixerGroups = 0;
2045
2046    handle->ready = false;   
2047}
2048
2049/*************************************************************************/
2050static void BAPE_StandardMixer_P_RemoveInputCallback(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector)
2051{
2052    (void)BAPE_StandardMixer_P_RemoveInput(pNode->pHandle, pConnector);
2053}
2054
2055
2056/*************************************************************************/
2057static BERR_Code BAPE_StandardMixer_P_AllocateMixerGroups(BAPE_MixerHandle handle)
2058{
2059    BERR_Code errCode=BERR_SUCCESS;
2060    BAPE_MixerGroupCreateSettings createSettings;
2061    unsigned i, numOutputs;
2062
2063    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
2064
2065#if BDBG_DEBUG_BUILD
2066    /* Sanity check, make sure all resources are marked invalid in the mixer */
2067    for ( i = 0; i < BAPE_CHIP_MAX_MIXERS; i++ )
2068    {
2069        BDBG_ASSERT(NULL == handle->mixerGroups[i]);
2070    }
2071    BDBG_ASSERT(handle->numMixerGroups == 0);
2072#endif
2073
2074    BAPE_MixerGroup_P_GetDefaultCreateSettings(&createSettings);
2075    createSettings.numChannelPairs = handle->numChannelPairs;
2076    numOutputs = handle->numOutputs + handle->numOutputConnections;
2077    /* TODO: Can compact this into fewer mixers or possibly use cascading again. */
2078    for ( i = 0; i < numOutputs; i++ )
2079    {
2080        errCode = BAPE_MixerGroup_P_Create(handle->deviceHandle, &createSettings, &handle->mixerGroups[i]);
2081        if ( errCode )
2082        {
2083            goto err_create_group;
2084        }
2085        handle->numMixerGroups++;
2086    }
2087
2088    return BERR_SUCCESS;
2089
2090    err_create_group:
2091    for ( i = 0; i < handle->numMixerGroups; i++ )
2092    {
2093        BAPE_MixerGroup_P_Destroy(handle->mixerGroups[i]);
2094        handle->mixerGroups[i] = NULL;
2095    }
2096    handle->numMixerGroups = 0;
2097
2098    return errCode;       
2099}
2100
2101/*************************************************************************/
2102/* Declare the interface struct containing the API callbacks */
2103
2104#define NOT_SUPPORTED(x) NULL
2105/* If any of the APIs are not supported by a particular type of mixer,
2106 * just add a placeholder like this:
2107 *   NOT_SUPPORTED(BAPE_StandardMixer_P_RemoveAllInputs)
2108 */
2109
2110static const BAPE_MixerInterface  standardMixerInterface  = {
2111    BAPE_StandardMixer_P_Destroy,                /*       (*destroy)           */
2112    NOT_SUPPORTED(BAPE_StandardMixer_P_Start),   /*       (*start)             */
2113    NOT_SUPPORTED(BAPE_StandardMixer_P_Stop),    /*       (*stop)              */
2114    BAPE_StandardMixer_P_AddInput,               /*       (*addInput)          */
2115    BAPE_StandardMixer_P_RemoveInput,            /*       (*removeInput)       */
2116    BAPE_StandardMixer_P_RemoveAllInputs,        /*       (*removeAllInputs)   */
2117    BAPE_StandardMixer_P_AddOutput,              /*       (*addOutput)         */
2118    BAPE_StandardMixer_P_RemoveOutput,           /*       (*removeOutput)      */
2119    BAPE_StandardMixer_P_RemoveAllOutputs,       /*       (*removeAllOutputs)  */
2120    BAPE_StandardMixer_P_GetInputVolume,         /*       (*getInputVolume)    */
2121    BAPE_StandardMixer_P_SetInputVolume,         /*       (*setInputVolume)    */
2122    BAPE_StandardMixer_P_ApplyOutputVolume,      /*       (*applyOutputVolume) */
2123    BAPE_StandardMixer_P_SetSettings             /*       (*setSettings) */
2124};
2125
Note: See TracBrowser for help on using the repository browser.