source: svn/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_mixer_dsp.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: 65.2 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_dsp.c $
11 * $brcm_Revision: Hydra_Software_Devel/22 $
12 * $brcm_Date: 3/22/12 4:22p $
13 *
14 * Module Description: Mixer Interface for DSP Mixers
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/ape/7422/bape_mixer_dsp.c $
19 *
20 * Hydra_Software_Devel/22   3/22/12 4:22p jgarrett
21 * SW7425-2644: Ensuring output format is set properly with only a single
22 * input
23 *
24 * Hydra_Software_Devel/21   3/7/12 4:35p jgarrett
25 * SW7435-24: Adding DSP index for decode and dsp mixer
26 *
27 * Hydra_Software_Devel/20   12/2/11 3:19p jgarrett
28 * SW7346-578: Adding ability to change some mixer settings without
29 * destroying and re-creating the mixer
30 *
31 * Hydra_Software_Devel/19   11/14/11 3:40p gskerl
32 * SW7429-18: Merging 7429 changes back to main branch.
33 *
34 * Hydra_Software_Devel/SW7429-18/1   10/21/11 6:29p jgarrett
35 * SW7429-18: Initial compileable version for 7429
36 *
37 * Hydra_Software_Devel/18   10/14/11 12:11p jgarrett
38 * SW7425-468: Adding hooks for NRT DSP mixer support
39 *
40 * Hydra_Software_Devel/17   9/28/11 2:48p jgarrett
41 * SW7425-1119: Allowing compressed inputs to DSP mixer
42 *
43 * Hydra_Software_Devel/16   8/25/11 6:27p gskerl
44 * SW7425-1119: Finished adding BAPE_Mixer_Start() and BAPE_Mixer_Stop()
45 * support for dspMixers.
46 *
47 * Hydra_Software_Devel/15   8/23/11 1:43p gskerl
48 * SW7425-406: Corrected code that determines whether an FS is needed when
49 * there are multiple mixer inputs. Added code to propagate the sample
50 * rate to downstream nodes.
51 *
52 * Hydra_Software_Devel/14   8/23/11 1:24p gskerl
53 * SW7425-1119: Added prototypes and stubs for BAPE_Mixer_Start() and
54 * BAPE_Mixer_Stop(). For now, they just return BERR_NOT_SUPPORTED
55 *
56 * Hydra_Software_Devel/13   8/22/11 10:34a jgarrett
57 * SWDTV-8271: Changing timebase field name
58 *
59 * Hydra_Software_Devel/12   7/27/11 4:17p gskerl
60 * SW7425-884: Corrected arguments being passed to
61 * BAPE_P_DetachMixerFromPll() and BAPE_P_DetachMixerFromNco
62 *
63 * Hydra_Software_Devel/11   7/8/11 4:53p gskerl
64 * SW7425-321: Added printing of downstream nodes when an audio path is
65 * started (if bape_startprint is enabled)
66 *
67 * Hydra_Software_Devel/10   7/8/11 4:31p gskerl
68 * SW7552-72: Added support for NCO/Mclkgen audio clock sources
69 *
70 * Hydra_Software_Devel/9   6/28/11 10:33a jgarrett
71 * SW7422-406: Setting input volume for DSP mixers
72 *
73 * Hydra_Software_Devel/8   6/21/11 9:22a jgarrett
74 * SW7425-406: Coverity CID 443
75 *
76 * Hydra_Software_Devel/7   6/20/11 7:02p jgarrett
77 * SW7425-406: Adding input scaling coefficients to mixer
78 *
79 * Hydra_Software_Devel/6   6/16/11 11:03a gskerl
80 * SW7425-321: Added call to BAPE_Mixer_P_PrintMixers() just before
81 * starting paths
82 *
83 * Hydra_Software_Devel/5   6/15/11 6:27p jgarrett
84 * SW7425-406: Coverity CID 437
85 *
86 * Hydra_Software_Devel/4   6/14/11 3:46p jgarrett
87 * SW7425-406: Merge to main branch
88 *
89 * Hydra_Software_Devel/SW7425-406/4   6/13/11 7:27p jgarrett
90 * SW7425-406: Updates for new BDSP_Task_AddStageInput APIs
91 *
92 * Hydra_Software_Devel/SW7425-406/3   6/8/11 6:55p jgarrett
93 * SW7425-406: Adding support for multichannel and playback inputs to DSP
94 * mixer
95 *
96 * Hydra_Software_Devel/SW7425-406/2   6/6/11 8:53a jgarrett
97 * SW7425-406: Fixing inter-task buffer logic
98 *
99 * Hydra_Software_Devel/SW7425-406/1   6/3/11 6:42p jgarrett
100 * SW7425-406: Initial working version
101 *
102 * Hydra_Software_Devel/3   6/2/11 2:12p jgarrett
103 * SW7425-406: Removing feedback buffer
104 *
105 * Hydra_Software_Devel/2   6/1/11 6:31p jgarrett
106 * SW7425-406: Adding additional DSP inter-task resource managment
107 *
108 * Hydra_Software_Devel/1   5/31/11 6:37p jgarrett
109 * SW7425-406: Adding initial DSP mixer code
110 *
111 ***************************************************************************/
112
113#include "bstd.h"
114#include "bkni.h"
115#include "bape.h"
116#include "bape_priv.h"
117#include "bdsp_raaga.h"
118
119BDBG_MODULE(bape_mixer_dsp);
120
121/* Mixer Interface */
122static const BAPE_MixerInterface  g_dspMixerInterface;
123
124/* Node callbacks */
125static BERR_Code BAPE_DspMixer_P_AllocatePathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
126static void      BAPE_DspMixer_P_FreePathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
127static BERR_Code BAPE_DspMixer_P_ConfigPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
128static BERR_Code BAPE_DspMixer_P_StartPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
129static void      BAPE_DspMixer_P_StopPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
130static void      BAPE_DspMixer_P_InputSampleRateChange_isr(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
131static BERR_Code BAPE_DspMixer_P_InputFormatChange(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection);
132static void      BAPE_DspMixer_P_InputMute(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection, bool enabled);
133static BERR_Code BAPE_DspMixer_P_ConnectorSupported(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector);
134static void      BAPE_DspMixer_P_RemoveInputCallback(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector);
135
136/* Local Routines */
137static BERR_Code BAPE_DspMixer_P_RemoveAllInputs(BAPE_MixerHandle handle);
138static BERR_Code BAPE_DspMixer_P_StartTask(BAPE_MixerHandle handle);
139static void BAPE_DspMixer_P_StopTask(BAPE_MixerHandle handle);
140static void BAPE_DspMixer_P_CleanupTaskCreateSettings(BAPE_MixerHandle handle);
141static void BAPE_DspMixer_P_FreeConnectionResources(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection);
142static BERR_Code BAPE_DspMixer_P_AllocateLoopbackInput(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection);
143static void BAPE_DspMixer_P_SetSampleRate_isr(BAPE_MixerHandle mixer, unsigned sampleRate);
144static void BAPE_DspMixer_P_SetInputSRC_isr(BAPE_MixerHandle mixer, BAPE_Connector input, unsigned inputRate, unsigned outputRate);
145static BERR_Code BAPE_DspMixer_P_ApplyInputVolume(BAPE_MixerHandle mixer, unsigned index);
146
147BERR_Code BAPE_DspMixer_P_Create(
148    BAPE_Handle deviceHandle,
149    const BAPE_MixerSettings *pSettings,
150    BAPE_MixerHandle *pHandle               /* [out] */
151    )
152{
153    BERR_Code errCode;
154    BAPE_MixerHandle handle;
155    BAPE_MixerSettings defaultSettings;
156
157    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
158    BDBG_ASSERT(NULL != pHandle);
159
160    *pHandle = NULL;
161
162    if ( NULL == pSettings )
163    {
164        BAPE_Mixer_GetDefaultSettings(&defaultSettings);
165        pSettings = &defaultSettings;
166    }
167
168    if ( NULL == deviceHandle->dspContext )
169    {
170        BDBG_ERR(("DSP support is not available.  Can't create a DSP mixer."));
171        return BERR_TRACE(BERR_NOT_SUPPORTED);
172    }
173
174    if ( pSettings->dspIndex >= deviceHandle->numDsps )
175    {
176        BDBG_ERR(("DSP %u is not available.  This system has %u DSPs.", pSettings->dspIndex, deviceHandle->numDsps));
177        return BERR_TRACE(BERR_INVALID_PARAMETER);
178    }
179
180    if ( pSettings->outputDelay )
181    {
182        BDBG_WRN(("Output delay is not supported for DSP mixers.  Ignoring outputDelay value."));
183    }
184
185    handle = BKNI_Malloc(sizeof(BAPE_Mixer));
186    if ( NULL == handle )
187    {
188        errCode = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
189        goto err_handle;
190    }
191
192    BKNI_Memset(handle, 0, sizeof(BAPE_Mixer));
193    BDBG_OBJECT_SET(handle, BAPE_Mixer);
194    handle->settings = *pSettings;
195    handle->interface = &g_dspMixerInterface;
196    handle->deviceHandle = deviceHandle;
197    BLST_S_INSERT_HEAD(&deviceHandle->mixerList, handle, node);
198    handle->sampleRate = 0;
199    handle->fs = BAPE_FS_INVALID;
200    BAPE_P_InitPathNode(&handle->pathNode, BAPE_PathNodeType_eMixer, handle->settings.type, 1, deviceHandle, handle);
201    handle->pathNode.subtype = BAPE_MixerType_eDsp;
202    handle->pathNode.pName = "DSP Mixer";
203    handle->pathNode.paths[0].connector.dataSource = BAPE_DataSource_eDspBuffer;
204    handle->pathNode.paths[0].connector.numChannelPairs = 1;
205    handle->pathNode.paths[0].connector.useBufferPool = true;
206
207    /* Fill in node connection routines */
208    handle->pathNode.allocatePathFromInput = BAPE_DspMixer_P_AllocatePathFromInput;
209    handle->pathNode.freePathFromInput = BAPE_DspMixer_P_FreePathFromInput;
210    handle->pathNode.configPathFromInput = BAPE_DspMixer_P_ConfigPathFromInput;
211    handle->pathNode.startPathFromInput = BAPE_DspMixer_P_StartPathFromInput;
212    handle->pathNode.stopPathFromInput = BAPE_DspMixer_P_StopPathFromInput;
213
214    /* Generic Routines for DSP nodes */
215    handle->pathNode.allocatePathToOutput = BAPE_DSP_P_AllocatePathToOutput;
216    handle->pathNode.configPathToOutput = BAPE_DSP_P_ConfigPathToOutput;
217    handle->pathNode.stopPathToOutput = BAPE_DSP_P_StopPathToOutput;
218    handle->pathNode.startPathToOutput = BAPE_DSP_P_StartPathToOutput;
219
220    /* Other misc. node routines for mixers */
221    handle->pathNode.inputSampleRateChange_isr = BAPE_DspMixer_P_InputSampleRateChange_isr;
222    handle->pathNode.inputFormatChange = BAPE_DspMixer_P_InputFormatChange;
223    handle->pathNode.inputMute = BAPE_DspMixer_P_InputMute;
224    handle->pathNode.connectorSupported = BAPE_DspMixer_P_ConnectorSupported;
225    handle->pathNode.removeInput = BAPE_DspMixer_P_RemoveInputCallback;
226
227    handle->pPrimaryBranch = BKNI_Malloc(sizeof(BDSP_CIT_P_FwBranchInfo));
228    if ( NULL == handle->pPrimaryBranch )
229    {
230        errCode = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
231        goto err_branch;
232    }
233
234    *pHandle = handle;
235
236    return BERR_SUCCESS;
237
238    BKNI_Free(handle->pPrimaryBranch);
239err_branch:
240    BLST_S_REMOVE(&handle->deviceHandle->mixerList, handle, BAPE_Mixer, node);
241    BDBG_OBJECT_DESTROY(handle, BAPE_Mixer);
242    BKNI_Free(handle);
243err_handle:
244    return errCode;
245}
246
247static void BAPE_DspMixer_P_Destroy(
248    BAPE_MixerHandle handle
249    )
250{
251    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
252   
253    /* Make sure no inputs are running. */
254    if ( handle->running )
255    {
256        BDBG_ERR(("Mixer %p (%d) is running.  Cannot close.", handle, handle->index));
257        BDBG_ASSERT(false == handle->running);
258        return;
259    }
260
261    /* Remove all inputs */
262    BAPE_DspMixer_P_RemoveAllInputs(handle);
263
264    /* Unlink from device */
265    BLST_S_REMOVE(&handle->deviceHandle->mixerList, handle, BAPE_Mixer, node);
266
267    /* Free Allocations */
268    BKNI_Free(handle->pPrimaryBranch);
269
270    /* Destroy Handle */
271    BDBG_OBJECT_DESTROY(handle, BAPE_Mixer);
272    BKNI_Free(handle);
273}
274
275static BERR_Code BAPE_DspMixer_P_AddInput(
276    BAPE_MixerHandle handle,
277    BAPE_Connector input,
278    const BAPE_MixerAddInputSettings *pSettings     /* Optional, pass NULL for default settings */
279    )
280{
281    unsigned i;
282    BERR_Code errCode;
283    BAPE_MixerAddInputSettings defaultSettings;
284    bool makeMaster;
285
286    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
287    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
288
289    if ( NULL == pSettings )
290    {
291        pSettings = &defaultSettings;
292        BAPE_Mixer_GetDefaultAddInputSettings(&defaultSettings);
293    }
294
295    makeMaster = pSettings->sampleRateMaster;
296
297    if ( handle->running )
298    {
299        BDBG_ERR(("Cannot change inputs while a mixer is active."));
300        return BERR_TRACE(BERR_NOT_SUPPORTED);
301    }
302
303#if BDBG_DEBUG_BUILD
304    /* Make sure the same input isn't added multiple times */
305    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
306    {
307        if ( handle->inputs[i] == input )
308        {
309            BDBG_ERR(("Cannot add the same input multiple times to a single mixer."));
310            return BERR_TRACE(BERR_NOT_SUPPORTED);
311        }
312    }
313#endif
314
315    if ( makeMaster && input->dataSource != BAPE_DataSource_eDspBuffer )
316    {
317        BDBG_ERR(("Only DSP inputs can be treated as master for DSP mixers"));
318        return BERR_TRACE(BERR_NOT_SUPPORTED);
319    }
320
321    /* Find empty slot */
322    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
323    {
324        if ( handle->inputs[i] == NULL )
325        {
326            handle->inputs[i] = input;
327            BDBG_MSG(("Adding input %s %s to DSP mixer %u as %s", input->pParent->pName, input->pName, handle->index, makeMaster?"master":"slave"));
328            if ( makeMaster )
329            {
330                if ( handle->master )
331                {
332                    BDBG_WRN(("Replacing current master input with new input"));
333                }
334                handle->master = input;
335            }
336            BAPE_Mixer_P_GetDefaultInputVolume(&handle->inputVolume[i]);
337            errCode = BAPE_PathNode_P_AddInput(&handle->pathNode, input);
338            if ( errCode )
339            {
340                handle->inputs[i] = NULL;
341                return BERR_TRACE(errCode);
342            }
343            return BERR_SUCCESS;
344        }
345    }
346
347    /* Mixer has no available slots. */
348    BDBG_ERR(("Mixer can not accept any more inputs.  Maximum inputs per mixer is %u.", BAPE_CHIP_MAX_MIXER_INPUTS));
349    return BERR_TRACE(BERR_NOT_SUPPORTED);
350}
351
352static BERR_Code BAPE_DspMixer_P_RemoveInput(
353    BAPE_MixerHandle handle,
354    BAPE_Connector input
355    )
356{
357    unsigned i;
358    BERR_Code errCode;
359
360    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
361    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
362
363    if ( handle->running )
364    {
365        BDBG_ERR(("Cannot change inputs while a mixer is active."));
366        return BERR_TRACE(BERR_NOT_SUPPORTED);
367    }
368
369    /* Find slot containing this input */
370    i = BAPE_Mixer_P_FindInputIndex(handle, input);
371    if ( i < BAPE_CHIP_MAX_MIXER_INPUTS )
372    {
373        errCode = BAPE_PathNode_P_RemoveInput(&handle->pathNode, input);
374        if ( errCode )
375        {
376            return BERR_TRACE(errCode);
377        }
378        handle->inputs[i] = NULL;
379        if ( handle->master == input )
380        {
381            BDBG_MSG(("Removing master input %p", input));
382            handle->master = NULL;
383        }
384        return BERR_SUCCESS;
385    }
386
387    /* Input not found. */
388    BDBG_ERR(("Input %p is not connected to DSP mixer %p", input, handle));
389    return BERR_TRACE(BERR_INVALID_PARAMETER);
390}
391
392static BERR_Code BAPE_DspMixer_P_RemoveAllInputs(
393    BAPE_MixerHandle handle
394    )
395{
396    unsigned i;
397    BERR_Code errCode;
398
399    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
400
401    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
402    {
403        if ( handle->inputs[i] )
404        {
405            errCode = BAPE_DspMixer_P_RemoveInput(handle, handle->inputs[i]);
406            if ( errCode )
407            {
408                return BERR_TRACE(errCode);
409            }
410        }
411    }
412
413    return BERR_SUCCESS;
414}
415
416static BERR_Code BAPE_DspMixer_P_Start(BAPE_MixerHandle handle)
417{
418    BERR_Code errCode;
419    BAPE_PathNode *pNode;
420    unsigned numFound;
421
422    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
423
424    if ( handle->startedExplicity )
425    {
426        BDBG_ERR(("Mixer %p (%d) has already been explicity started.  Can't start.", handle, handle->index));
427        return BERR_TRACE(BERR_NOT_SUPPORTED);
428    }
429
430    /* Look for MuxOutput */
431    BAPE_PathNode_P_FindConsumersByType(&handle->pathNode, BAPE_PathNodeType_eMuxOutput, 1, &numFound, &pNode);
432    if ( numFound > 0 )
433    {
434        BAPE_MuxOutputHandle hMuxOutput = (BAPE_MuxOutputHandle)pNode->pHandle;
435        if ( !BAPE_MuxOutput_P_IsRunning(hMuxOutput) )
436        {
437            BDBG_ERR(("When explicitly starting a mixer for transcode operations, the MuxOutput object must be started first."));
438            return BERR_TRACE(BERR_NOT_SUPPORTED);
439        }
440    }
441
442    if ( NULL == handle->task )
443    {
444        BDBG_MSG(("BAPE_DspMixer_P_Start: Task not present.  Starting mixer task."));
445        errCode = BAPE_DspMixer_P_StartTask(handle);
446        if ( errCode )
447        {
448            return BERR_TRACE(errCode);
449        }
450    }
451   
452    BDBG_ASSERT(handle->startedExplicity == false);
453    handle->startedExplicity = true;
454    handle->running++;
455       
456    return BERR_SUCCESS;
457}
458
459
460static BERR_Code BAPE_DspMixer_P_StartTask(BAPE_MixerHandle handle)
461{
462    BERR_Code errCode;
463    bool fsRequired=false;
464    BAPE_PathConnection *pInputConnection;
465    BAPE_PathNode *pNode;
466    unsigned numFound;
467
468    /* Scan inputs and determine if we need a FS and PLL linkage for loopback */
469    for ( pInputConnection = BLST_S_FIRST(&handle->pathNode.upstreamList);
470          pInputConnection != NULL;
471          pInputConnection = BLST_S_NEXT(pInputConnection, upstreamNode) )
472    {
473        if ( pInputConnection->pSource->dataSource != BAPE_DataSource_eDspBuffer )
474        {
475            fsRequired = true;
476            break; 
477        }
478    }
479
480    if ( fsRequired )
481    {
482        /* Loopback found, allocate an FS timing object */
483#if BAPE_CHIP_MAX_FS > 0
484        BDBG_ASSERT(handle->fs == BAPE_FS_INVALID);
485        handle->fs = BAPE_P_AllocateFs(handle->deviceHandle);
486        if ( handle->fs == BAPE_FS_INVALID )
487        {
488            BDBG_ERR(("Unable to allocate FS resources for input loopback."));
489            errCode = BERR_TRACE(BERR_NOT_SUPPORTED);
490            goto err_fs;
491        }
492#endif
493        /* Use PLL for now, other timing sources are not available here. */
494        /* TODO: Allow for selection of NCO timing source... maybe even call
495         * BAPE_Mixer_P_GetMclkSource(), after moving it from "standard"
496         * mixer code to common mixer code. */ 
497        handle->mclkSource = BAPE_MclkSource_ePll0 + handle->settings.outputPll;
498
499        /* Connect to the appropriate PLL */
500        #if BAPE_CHIP_MAX_PLLS > 0
501        BAPE_P_AttachMixerToPll(handle, handle->settings.outputPll);
502        #else
503        errCode = BERR_TRACE(BERR_NOT_SUPPORTED);
504        goto err_acquire_resources;
505        #endif
506
507        /* Set Loopback-FS linkage */
508        for ( pInputConnection = BLST_S_FIRST(&handle->pathNode.upstreamList);
509              pInputConnection != NULL;
510              pInputConnection = BLST_S_NEXT(pInputConnection, upstreamNode) )
511        {
512            if ( pInputConnection->loopbackGroup )
513            {
514                BAPE_LoopbackGroupSettings loopbackSettings;
515                BAPE_LoopbackGroup_P_GetSettings(pInputConnection->loopbackGroup, &loopbackSettings);
516#if BAPE_CHIP_MAX_FS > 0
517                loopbackSettings.fs = handle->fs;
518#else
519                loopbackSettings.mclkSource = handle->mclkSource;
520                loopbackSettings.pllChannel = 0;
521                loopbackSettings.mclkFreqToFsRatio = BAPE_BASE_PLL_TO_FS_RATIO;
522#endif
523                errCode = BAPE_LoopbackGroup_P_SetSettings(pInputConnection->loopbackGroup, &loopbackSettings);
524                if ( errCode )
525                {
526                    errCode = BERR_TRACE(errCode);
527                    goto err_acquire_resources;
528                }
529            }
530            break;
531        }
532
533    }
534    else
535    {
536        handle->mclkSource = BAPE_MclkSource_eNone;
537    }
538
539
540    BDSP_Task_GetDefaultCreateSettings(handle->deviceHandle->dspContext, &handle->taskCreateSettings);
541
542    /* Setup default branch */
543    handle->taskCreateSettings.numBranches = 1;
544    handle->taskCreateSettings.pBranchInfo[0] = handle->pPrimaryBranch;
545
546    /* TODO: Should this be inheritied from children or does it matter? */
547    handle->taskCreateSettings.timeBaseType = BDSP_AF_P_TimeBaseType_e45Khz;
548    handle->taskCreateSettings.schedulingMode = BDSP_TaskSchedulingMode_eMaster;
549    BAPE_DSP_P_InitBranch(handle->pPrimaryBranch);
550    handle->pPrimaryBranch->ui32NumStages = 1;
551    handle->pPrimaryBranch->sFwStgInfo[0].ui32BranchId = 0;
552    handle->pPrimaryBranch->sFwStgInfo[0].ui32StageId = 0;
553    handle->pPrimaryBranch->sFwStgInfo[0].eStageType = BDSP_CIT_P_StageType_ePostProc;
554    handle->pPrimaryBranch->sFwStgInfo[0].uAlgorithm.eProcAudioAlgo = BDSP_AudioProcessing_eFWMixer;
555    handle->pPrimaryBranch->sFwStgInfo[0].uAudioMode.eProcessingAudioMode = BDSP_DSPCHN_ProcessingMode_ePP;
556    handle->pPrimaryBranch->sFwStgInfo[0].sStgConnectivity.ui32NumSrc = 0;    /* Inputs will be added later. */       
557    BKNI_Memset(&handle->pPrimaryBranch->sFwStgInfo[0].sStgConnectivity.sSrcDetails[0], 0, 
558                sizeof(handle->pPrimaryBranch->sFwStgInfo[0].sStgConnectivity.sSrcDetails[0]));
559
560    /* Prepare Connector */
561    handle->pathNode.paths[0].connector.pTaskCreateSettings = &handle->taskCreateSettings;
562    handle->pathNode.paths[0].connector.branchId = 0;
563    handle->pathNode.paths[0].connector.stageId = 0;
564
565    /* Prepare subnodes */
566    errCode = BAPE_PathNode_P_AcquirePathResources(&handle->pathNode);
567    if ( errCode )
568    {
569        errCode = BERR_TRACE(errCode);
570        goto err_acquire_resources;
571    }
572    handle->sampleRate = 0;
573
574    /* Validate we either have real-time outputs or don't depending on system requirements */
575    BAPE_PathNode_P_FindConsumersBySubtype(&handle->pathNode, BAPE_PathNodeType_eMixer, BAPE_MixerType_eStandard, 1, &numFound, &pNode);
576    if ( handle->taskCreateSettings.realtimeMode == BDSP_TaskRealtimeMode_eNonRealTime )
577    {
578        if ( numFound != 0 )
579        {
580            BDBG_ERR(("No outputs should be connected to a DSP mixer in non-realtime mode."));
581            return BERR_TRACE(BERR_NOT_SUPPORTED);
582        }
583    }
584    else
585    {
586        if ( numFound == 0 )
587        {
588            BDBG_ERR(("No outputs are connected.  Cannot start."));
589            return BERR_TRACE(BERR_INVALID_PARAMETER);
590        }
591    }
592
593    handle->taskCreateSettings.dspIndex = handle->settings.dspIndex;
594    errCode = BDSP_Task_Create(handle->deviceHandle->dspContext, &handle->taskCreateSettings, &handle->task);
595    if ( errCode )
596    {
597        errCode = BERR_TRACE(errCode);
598        goto err_task_create;
599    }
600
601    /* TODO: Apply TSM/Framesync settings */
602
603    handle->pathNode.paths[0].connector.sampleRate = 0;
604    handle->pathNode.paths[0].connector.task = handle->task;
605
606    /* Link the path resources */
607    errCode = BAPE_PathNode_P_ConfigurePathResources(&handle->pathNode);
608    if ( errCode )
609    {
610        errCode = BERR_TRACE(errCode);
611        goto err_config_path;
612    }
613
614    #if BDBG_DEBUG_BUILD
615        BAPE_Mixer_P_PrintMixers(handle->deviceHandle);
616    #endif
617
618    /* Start the consumers */
619    errCode = BAPE_PathNode_P_StartPaths(&handle->pathNode);
620    if ( errCode )
621    {
622        errCode = BERR_TRACE(errCode);
623        goto err_start_path;
624    }
625
626    #if BDBG_DEBUG_BUILD
627        BAPE_Mixer_P_PrintDownstreamNodes(&handle->pathNode);
628    #endif
629
630    /* Start the DSP Task */
631    errCode = BDSP_Task_Start(handle->task);
632    if ( errCode )
633    {
634        errCode = BERR_TRACE(errCode);
635        goto err_start_task;
636    }
637   
638    return BERR_SUCCESS;
639
640err_start_task:
641err_start_path:
642err_config_path:
643    BDSP_Task_Destroy(handle->task);
644    handle->task = NULL;
645err_task_create:
646err_acquire_resources:
647    BAPE_PathNode_P_ReleasePathResources(&handle->pathNode);
648    BAPE_DspMixer_P_CleanupTaskCreateSettings(handle);   
649    if ( fsRequired )
650    {
651        BAPE_P_FreeFs(handle->deviceHandle, handle->fs);
652        handle->fs = BAPE_FS_INVALID;
653    }
654#if BAPE_CHIP_MAX_FS > 0
655err_fs:
656#endif
657    return errCode;
658}
659
660static BERR_Code BAPE_DspMixer_P_AllocatePathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
661{
662    BAPE_MixerHandle handle;
663    BERR_Code errCode;
664    unsigned i;
665    void *pCached;
666    uint32_t base, end;
667    BDSP_AF_P_sIO_BUFFER *pIoDescriptor;
668    BDSP_AF_P_sIO_GENERIC_BUFFER *pGenericDescriptor;
669
670    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
671    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
672
673    handle = (BAPE_MixerHandle)pNode->pHandle;
674    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
675
676    /* Sanity check if the dsp indexes match */
677    if ( pConnection->pSource->dataSource == BAPE_DataSource_eDspBuffer )
678    {
679        if ( pConnection->pSource->pTaskCreateSettings->dspIndex != handle->settings.dspIndex )
680        {
681            BDBG_ERR(("All inputs to a DSP mixer must run on the same task as the DSP mixer."));
682            BDBG_ERR(("This mixer is configured for DSP %u but the input %s is configured for DSP %u",
683                      handle->settings.dspIndex, pConnection->pSource->pParent->pName,
684                      pConnection->pSource->pTaskCreateSettings->dspIndex));
685            return BERR_TRACE(BERR_NOT_SUPPORTED);
686        }
687    }
688
689    /* First see if we need to create the mixer task itself */
690    if ( NULL == handle->task )
691    {
692        BDBG_MSG(("AllocatePathFromInput: Task not present.  Starting mixer task."));
693        errCode = BAPE_DspMixer_P_StartTask(handle);
694        if ( errCode )
695        {
696            return BERR_TRACE(errCode);
697        }
698    }
699
700    /* Task Handle is valid if we reach here. */
701   
702    switch ( pConnection->pSource->dataSource )
703    {
704    case BAPE_DataSource_eDspBuffer:
705        /* Set mixer task as the master for the input task */
706        pConnection->pSource->pTaskCreateSettings->schedulingMode = BDSP_TaskSchedulingMode_eSlave;
707        pConnection->pSource->pTaskCreateSettings->masterTask = handle->task;
708        pConnection->pSource->pTaskCreateSettings->realtimeMode = handle->taskCreateSettings.realtimeMode;
709
710        /* Allocate required buffers */
711        if ( NULL == pConnection->pInterTaskGenericBuffer )
712        {
713            pConnection->pInterTaskGenericBuffer = BMEM_Heap_Alloc(handle->deviceHandle->memHandle, BDSP_AF_P_INTERTASK_IOGENBUFFER_SIZE);
714            if ( NULL == pConnection->pInterTaskGenericBuffer )
715            {
716                BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);
717                return BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
718            }
719        }
720        if ( NULL == pConnection->pInterTaskIoBuffer )
721        {
722            pConnection->pInterTaskIoBuffer = BMEM_Heap_Alloc(handle->deviceHandle->memHandle, 2 * pConnection->pSource->numChannelPairs * (BAPE_P_INTER_TASK_BUFFER_SIZE));
723            if ( NULL == pConnection->pInterTaskIoBuffer )
724            {
725                BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);
726                return BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
727            }
728        }
729        if ( NULL == pConnection->pInterTaskIoDescriptor )
730        {
731            pConnection->pInterTaskIoDescriptor = BMEM_Heap_Alloc(handle->deviceHandle->memHandle, sizeof(BDSP_AF_P_sIO_BUFFER));
732            if ( NULL == pConnection->pInterTaskIoDescriptor )
733            {
734                BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);
735                return BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
736            }
737        }
738        /* Initialize IO Buffer Descriptor */
739        (void)BMEM_Heap_ConvertAddressToCached(handle->deviceHandle->memHandle, pConnection->pInterTaskIoDescriptor, &pCached);
740        pIoDescriptor = pCached;
741        pIoDescriptor->eBufferType = BDSP_AF_P_BufferType_eDRAM;
742        if ( pConnection->pSource->compressed )
743        {
744            pIoDescriptor->ui32NumBuffers = 1;
745        }
746        else
747        {
748            pIoDescriptor->ui32NumBuffers = 2*pConnection->pSource->numChannelPairs;
749        }
750        for ( i = 0; i < pIoDescriptor->ui32NumBuffers; i++ )
751        {
752            BMEM_ConvertAddressToOffset(handle->deviceHandle->memHandle, pConnection->pInterTaskIoBuffer, &base);
753            base += i*BAPE_P_INTER_TASK_BUFFER_SIZE;
754            end = base+(BAPE_P_INTER_TASK_BUFFER_SIZE);
755            pIoDescriptor->sCircBuffer[i].ui32BaseAddr = base;
756            pIoDescriptor->sCircBuffer[i].ui32ReadAddr = base;
757            pIoDescriptor->sCircBuffer[i].ui32WriteAddr = base;
758            pIoDescriptor->sCircBuffer[i].ui32EndAddr = end;
759            pIoDescriptor->sCircBuffer[i].ui32WrapAddr = end;
760        }
761        for ( i = pIoDescriptor->ui32NumBuffers; i < BDSP_AF_P_MAX_CHANNELS; i++ )
762        {
763            BKNI_Memset(&pIoDescriptor->sCircBuffer[i], 0, sizeof(pIoDescriptor->sCircBuffer[i]));
764        }
765        BMEM_Heap_FlushCache(handle->deviceHandle->memHandle, pIoDescriptor, sizeof(BDSP_AF_P_sIO_BUFFER));
766        if ( NULL == pConnection->pInterTaskGenericDescriptor )
767        {
768            pConnection->pInterTaskGenericDescriptor = BMEM_Heap_Alloc(handle->deviceHandle->memHandle, sizeof(BDSP_AF_P_sIO_GENERIC_BUFFER));
769            if ( NULL == pConnection->pInterTaskGenericDescriptor )
770            {
771                BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);
772                return BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
773            }
774        }
775        /* Initialize IO Generic Buffer Descriptor */
776        (void)BMEM_Heap_ConvertAddressToCached(handle->deviceHandle->memHandle, pConnection->pInterTaskGenericDescriptor, &pCached);
777        pGenericDescriptor = pCached;
778        BKNI_Memset(pGenericDescriptor, 0, sizeof(BDSP_AF_P_sIO_GENERIC_BUFFER));
779        pGenericDescriptor->eBufferType = BDSP_AF_P_BufferType_eDRAM;
780        pGenericDescriptor->ui32NumBuffers = 1;
781        BMEM_ConvertAddressToOffset(handle->deviceHandle->memHandle, pConnection->pInterTaskGenericBuffer, &base);
782        end = base+BDSP_AF_P_INTERTASK_IOGENBUFFER_SIZE;
783        pGenericDescriptor->sCircBuffer.ui32BaseAddr = base;
784        pGenericDescriptor->sCircBuffer.ui32ReadAddr = base;
785        pGenericDescriptor->sCircBuffer.ui32WriteAddr = base;
786        pGenericDescriptor->sCircBuffer.ui32EndAddr = end;
787        pGenericDescriptor->sCircBuffer.ui32WrapAddr = end;
788        BMEM_Heap_FlushCache(handle->deviceHandle->memHandle, pGenericDescriptor, sizeof(BDSP_AF_P_sIO_GENERIC_BUFFER));
789        break;
790    case BAPE_DataSource_eHostBuffer:
791    case BAPE_DataSource_eDfifo:
792    case BAPE_DataSource_eFci:
793        errCode = BAPE_DspMixer_P_AllocateLoopbackInput(handle, pConnection);
794        if ( errCode )
795        {
796            return BERR_TRACE(errCode);
797        }
798        break;
799    default:
800        BDBG_ERR(("Unsupported input type"));
801        return BERR_TRACE(BERR_NOT_SUPPORTED);
802    }
803
804    return BERR_SUCCESS;
805}
806
807static void BAPE_DspMixer_P_FreePathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
808{
809    BAPE_MixerHandle handle;
810
811    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
812    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
813
814    handle = (BAPE_MixerHandle)pNode->pHandle;
815    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
816
817    BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);
818
819    /* Stop the mixer task if nobody is running. */
820    if ( 0 == handle->running && handle->task )
821    {
822        BDBG_MSG(("FreePathFromInput: No running inputs - stop mixer task"));
823        BAPE_DspMixer_P_StopTask(handle);
824    }
825}
826
827static BERR_Code BAPE_DspMixer_P_ConfigPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
828{
829    BAPE_MixerHandle handle;
830
831    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
832    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
833
834    handle = (BAPE_MixerHandle)pNode->pHandle;
835    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
836
837    return BERR_SUCCESS;
838}
839
840static BERR_Code BAPE_DspMixer_P_GetFwSrcType(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection, BDSP_CIT_P_FwStgSrcDstType *pType)
841{
842    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
843    BDBG_ASSERT(NULL != pType);
844
845    switch ( pConnection->pSource->dataSource )   
846    {
847    case BAPE_DataSource_eDspBuffer:
848        *pType = BDSP_CIT_P_FwStgSrcDstType_eInterTaskDRAMBuf;
849        break;
850    case BAPE_DataSource_eHostBuffer:
851    case BAPE_DataSource_eDfifo:
852    case BAPE_DataSource_eFci:
853        /* DFIFO Input */
854        *pType = BDSP_CIT_P_FwStgSrcDstType_eFMMBuf;
855        break;
856    default:
857        BDBG_ERR(("Unsupported input type"));
858        *pType = BDSP_CIT_P_FwStgSrcDstType_eInvalid;
859        return BERR_TRACE(BERR_NOT_SUPPORTED);
860    }
861
862    return BERR_SUCCESS;
863}
864
865static BERR_Code BAPE_DspMixer_P_GetFwSrcDetails(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection, BDSP_CIT_P_FwStgSrcDstDetails *pDetails)
866{
867    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
868
869    switch ( pConnection->pSource->dataSource )   
870    {
871    case BAPE_DataSource_eDspBuffer:
872        pDetails->eType = BDSP_CIT_P_FwStgSrcDstType_eInterTaskDRAMBuf;
873        BMEM_Heap_ConvertAddressToOffset(pConnection->pSink->deviceHandle->memHandle, 
874                                         pConnection->pInterTaskIoDescriptor,
875                                         &pDetails->uDetails.sInterTaskDramBuffCfg.ui32IoBuffCfgAddr);
876
877        BMEM_Heap_ConvertAddressToOffset(pConnection->pSink->deviceHandle->memHandle, 
878                                         pConnection->pInterTaskGenericDescriptor,
879                                         &pDetails->uDetails.sInterTaskDramBuffCfg.ui32IoGenericBuffCfgAddr);
880        break;
881    case BAPE_DataSource_eHostBuffer:
882    case BAPE_DataSource_eDfifo:
883    case BAPE_DataSource_eFci:
884        /* DFIFO Input */
885        BAPE_DSP_P_GetDfifoSrcDetails(handle->deviceHandle, pConnection->dfifoGroup, 2*pConnection->pSource->numChannelPairs, false, pDetails);
886        break;
887    default:
888        BDBG_ERR(("Unsupported input type"));
889        return BERR_TRACE(BERR_NOT_SUPPORTED);
890    }
891
892    return BERR_SUCCESS;
893}
894
895static BERR_Code BAPE_DspMixer_P_StartPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
896{
897    BERR_Code errCode;
898    BAPE_MixerHandle handle;
899    BDSP_CIT_P_FwStgSrcDstType srcType;
900    BDSP_TaskAddStageInputSettings addInputSettings;
901
902    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
903    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
904
905    handle = (BAPE_MixerHandle)pNode->pHandle;
906    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
907   
908    BDBG_MSG(("Input %s %s starting", pConnection->pSource->pParent->pName, pConnection->pSource->pName));
909
910    /* First, setup the sample rate since it may affect output programming. */
911    BKNI_EnterCriticalSection();
912    BAPE_DspMixer_P_InputSampleRateChange_isr(pNode, pConnection);
913    BKNI_LeaveCriticalSection();
914
915    /* For FMM sources, start the FMM data path */
916    if ( pConnection->dfifoGroup )
917    {
918        errCode = BAPE_DfifoGroup_P_Start(pConnection->dfifoGroup, false);
919        if ( errCode )
920        {
921            (void)BERR_TRACE(errCode);
922            goto err_dfifo_start;
923        }
924    }
925    if ( pConnection->loopbackGroup )
926    {
927        errCode = BAPE_LoopbackGroup_P_Start(pConnection->loopbackGroup);
928        if ( errCode )
929        {
930            (void)BERR_TRACE(errCode);
931            goto err_loopback_start;
932        }
933    }
934    if ( pConnection->mixerGroup )
935    {
936        errCode = BAPE_MixerGroup_P_StartOutput(pConnection->mixerGroup, 0);
937        if ( errCode )
938        {
939            (void)BERR_TRACE(errCode);
940            goto err_mixer_output;
941        }
942        errCode = BAPE_MixerGroup_P_StartInput(pConnection->mixerGroup, 0);
943        if ( errCode )
944        {
945            (void)BERR_TRACE(errCode);
946            goto err_mixer_input;
947        }
948    }
949    if ( pConnection->srcGroup )
950    {
951        errCode = BAPE_SrcGroup_P_Start(pConnection->srcGroup);
952        if ( errCode )
953        {
954            (void)BERR_TRACE(errCode);
955            goto err_src_start;
956        }
957    }
958
959    errCode = BAPE_DspMixer_P_GetFwSrcType(handle, pConnection, &srcType);
960    if ( errCode )
961    {
962        (void)BERR_TRACE(errCode);
963        goto err_get_details;
964    }
965
966    BDSP_Task_GetDefaultAddStageInputSettings(srcType, &addInputSettings);
967    addInputSettings.branchId = 0;
968    addInputSettings.stageId = 0;
969    errCode = BAPE_DspMixer_P_GetFwSrcDetails(handle, pConnection, &addInputSettings.sourceDetails);
970    if ( errCode )
971    {
972        (void)BERR_TRACE(errCode);
973        goto err_get_details;
974    }
975
976    /* Start input */
977    BDBG_ASSERT(NULL == pConnection->taskInput);
978    BDBG_MSG(("Adding input to FW Mixer for %s %s", pConnection->pSource->pParent->pName, pConnection->pSource->pName));
979    errCode = BDSP_Task_AddStageInput(handle->task, &addInputSettings, &pConnection->taskInput);
980    if ( errCode )
981    {
982        (void)BERR_TRACE(errCode);
983        goto err_add_input;
984    }
985
986    /* Refresh input scaling prior now that the input is valid to the mixer */   
987    errCode = BAPE_DspMixer_P_ApplyInputVolume(handle, BAPE_Mixer_P_FindInputIndex(handle, pConnection->pSource));
988    if ( errCode )
989    {
990        (void)BERR_TRACE(errCode);
991        goto err_input_scaling;
992    }
993
994    handle->running++;
995    return BERR_SUCCESS;
996
997err_input_scaling:
998    BDSP_Task_RemoveStageInput(pConnection->taskInput);
999    pConnection->taskInput = NULL;
1000err_add_input:
1001err_get_details:
1002    if ( pConnection->srcGroup )
1003    {
1004        BAPE_SrcGroup_P_Stop(pConnection->srcGroup);
1005    }
1006err_src_start:
1007    if ( pConnection->mixerGroup )
1008    {
1009        BAPE_MixerGroup_P_StopInput(pConnection->mixerGroup, 0);
1010    }
1011err_mixer_input:
1012    if( pConnection->mixerGroup )
1013    {
1014        BAPE_MixerGroup_P_StopOutput(pConnection->mixerGroup, 0);
1015    }
1016err_mixer_output:
1017    if ( pConnection->loopbackGroup )
1018    {
1019        BAPE_LoopbackGroup_P_Stop(pConnection->loopbackGroup);
1020    }
1021err_loopback_start:
1022    if ( pConnection->dfifoGroup )
1023    {
1024        BAPE_DfifoGroup_P_Stop(pConnection->dfifoGroup);
1025    }
1026err_dfifo_start:
1027    return errCode;
1028}
1029
1030static void BAPE_DspMixer_P_StopPathFromInput(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
1031{
1032    BERR_Code errCode;
1033    BAPE_MixerHandle handle;
1034
1035    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1036    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1037
1038    handle = (BAPE_MixerHandle)pNode->pHandle;
1039    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1040   
1041    BDBG_ASSERT(handle->running > 0);
1042
1043    BDBG_MSG(("Removing input from FW Mixer for %s %s", pConnection->pSource->pParent->pName, pConnection->pSource->pName));
1044    errCode = BDSP_Task_RemoveStageInput(pConnection->taskInput);
1045    BDBG_ASSERT(errCode == BERR_SUCCESS);   /* If this fails something has gone horribly wrong */
1046    pConnection->taskInput = NULL;
1047
1048    if ( pConnection->srcGroup )
1049    {
1050        BAPE_SrcGroup_P_Stop(pConnection->srcGroup);
1051    }
1052    if ( pConnection->mixerGroup )
1053    {
1054        BAPE_MixerGroup_P_StopInput(pConnection->mixerGroup, 0);
1055        BAPE_MixerGroup_P_StopOutput(pConnection->mixerGroup, 0);
1056    }
1057    if ( pConnection->loopbackGroup )
1058    {
1059        BAPE_LoopbackGroup_P_Stop(pConnection->loopbackGroup);
1060    }
1061    if ( pConnection->dfifoGroup )
1062    {
1063        BAPE_DfifoGroup_P_Stop(pConnection->dfifoGroup);
1064    }
1065
1066    handle->running--;
1067    /* Stop the mixer task if nobody is running. */
1068    if ( 0 == handle->running && handle->task )
1069    {
1070        BDBG_MSG(("FreePathFromInput: Last running input has stopped - stop mixer task"));
1071        BAPE_DspMixer_P_StopTask(handle);
1072    }
1073}
1074
1075/* TODO: Share with other mixers */
1076static void BAPE_DspMixer_P_InputSampleRateChange_isr(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
1077{
1078    BAPE_MixerHandle handle;
1079    unsigned sampleRate;
1080
1081    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1082    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1083    BKNI_ASSERT_ISR_CONTEXT();
1084
1085    handle = pNode->pHandle;
1086    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1087
1088    sampleRate = pConnection->pSource->sampleRate;
1089
1090    /* If we are setting the same rate, ignore it */
1091    if ( pConnection->sampleRate == sampleRate )
1092    {
1093        BDBG_MSG(("Input %s %s sample rate unchanged (%u)", pConnection->pSource->pParent->pName, pConnection->pSource->pName, pConnection->sampleRate));
1094        return;
1095    }
1096
1097    BDBG_MSG(("Input %s %s sample rate changed from %u to %u", pConnection->pSource->pParent->pName, pConnection->pSource->pName, pConnection->sampleRate, sampleRate));
1098
1099    /* Mark new sample rate in connection */
1100    pConnection->sampleRate = sampleRate;
1101
1102    /* Handle the sample rate master */
1103    if ( handle->master == pConnection->pSource )
1104    {
1105        if ( sampleRate != 0 )
1106        {
1107            /* Set mixer sample rate. */
1108            BAPE_DspMixer_P_SetSampleRate_isr(handle, sampleRate);
1109        }
1110        else if ( handle->sampleRate == 0 )
1111        {
1112            /* Make sure there is a valid sample rate */
1113            BAPE_DspMixer_P_SetSampleRate_isr(handle, handle->settings.defaultSampleRate);
1114        }
1115    }
1116    else
1117    {
1118        /* Make sure there is a valid sample rate */
1119        if ( handle->sampleRate == 0 )
1120        {
1121            BAPE_DspMixer_P_SetSampleRate_isr(handle, handle->settings.defaultSampleRate);
1122        }
1123    }
1124
1125    /* Update SRCs accordingly. */
1126    BAPE_DspMixer_P_SetInputSRC_isr(handle, pConnection->pSource, sampleRate, handle->sampleRate);
1127
1128    /* Propagate sample rate downstream */
1129    if ( handle->master == pConnection->pSource )
1130    {
1131        pNode->paths[0].connector.sampleRate = pConnection->pSource->sampleRate;
1132        BAPE_Connector_P_SampleRateChange_isr(&pNode->paths[0].connector);
1133    }
1134}
1135
1136static BERR_Code BAPE_DspMixer_P_InputFormatChange(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection)
1137{
1138    BERR_Code errCode;
1139    BAPE_MixerHandle handle;
1140    unsigned i, numChannelPairs=1;
1141    bool compressed = false;
1142
1143    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1144    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1145
1146    handle = (BAPE_MixerHandle)pNode->pHandle;
1147    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1148   
1149    /* See if input format has changed.  If not, do nothing. */
1150    if ( pConnection->numChannelPairs == pConnection->pSource->numChannelPairs ||
1151         pConnection->compressed != pConnection->pSource->compressed )
1152    {
1153        BDBG_MSG(("Input connection format change reported, but does not affect resource requirements."));
1154    }
1155    else
1156    {
1157        BDBG_MSG(("Input connection format change reported - freeing connection resources."));
1158        BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);
1159    }
1160
1161    /* Determine output format based on widest input format */
1162    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
1163    {
1164        if ( NULL != handle->inputs[i] )
1165        {
1166            BDBG_MSG(("Input %s %s [%u] has %u channel pairs", handle->inputs[i]->pParent->pName, handle->inputs[i]->pName, i, handle->inputs[i]->numChannelPairs));
1167            if ( handle->inputs[i]->numChannelPairs > numChannelPairs )
1168            {
1169                numChannelPairs = handle->inputs[i]->numChannelPairs;
1170            }
1171        }
1172    }
1173    compressed = pConnection->pSource->compressed;
1174
1175    /* If the output format has changed, propagate that downstream */
1176    BDBG_MSG(("Number of output channel pairs from DSP mixer was %u now %u", handle->numChannelPairs, numChannelPairs));
1177    if ( handle->numChannelPairs != numChannelPairs ||
1178         handle->compressed != compressed )
1179    {
1180        BDBG_MSG(("Mixer output format has changed.  Was %u channel pairs, now %u channel pairs (%s).", handle->pathNode.paths[0].connector.numChannelPairs, numChannelPairs, compressed?"Compressed":"PCM"));
1181        BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);   /* Resources will be allocated next time required. */
1182        handle->pathNode.paths[0].connector.numChannelPairs = numChannelPairs;
1183        handle->pathNode.paths[0].connector.compressed = compressed;
1184        handle->numChannelPairs = numChannelPairs;
1185        handle->compressed = compressed;
1186        errCode = BAPE_Connector_P_FormatChange(&handle->pathNode.paths[0].connector);
1187        if ( errCode )
1188        {
1189            return BERR_TRACE(errCode);
1190        }
1191    }
1192
1193    return BERR_SUCCESS;
1194}
1195
1196static void BAPE_DspMixer_P_InputMute(struct BAPE_PathNode *pNode, struct BAPE_PathConnection *pConnection, bool enabled)
1197{
1198    BSTD_UNUSED(pNode);
1199    BSTD_UNUSED(pConnection);
1200    BSTD_UNUSED(enabled);
1201    /* TODO */
1202}
1203
1204static BERR_Code BAPE_DspMixer_P_ConnectorSupported(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector)
1205{
1206    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1207    BDBG_OBJECT_ASSERT(pConnector, BAPE_PathConnector);
1208
1209    switch ( pConnector->dataSource )
1210    {
1211    case BAPE_DataSource_eDspBuffer:
1212        break;
1213    case BAPE_DataSource_eHostBuffer:
1214    case BAPE_DataSource_eDfifo:
1215    case BAPE_DataSource_eFci:
1216        /* For these input types, only handle PCM data */
1217        if ( pConnector->compressed )
1218        {
1219            BDBG_ERR(("Compressed input is only supported in DSP mixer from other DSP inputs."));
1220            return BERR_TRACE(BERR_NOT_SUPPORTED);
1221        }
1222        break;
1223    default:
1224        BDBG_ERR(("Unsupported DSP Mixer input from %s %s", pConnector->pParent->pName, pConnector->pName));
1225        return BERR_TRACE(BERR_INVALID_PARAMETER);
1226    }
1227
1228    return BERR_SUCCESS;
1229}
1230
1231static void BAPE_DspMixer_P_RemoveInputCallback(struct BAPE_PathNode *pNode, BAPE_PathConnector *pConnector)
1232{
1233    BAPE_DspMixer_P_RemoveInput(pNode->pHandle, pConnector);
1234}
1235
1236static void BAPE_DspMixer_P_Stop(BAPE_MixerHandle handle)
1237{
1238    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1239
1240    if ( !handle->running )
1241    {
1242        BDBG_MSG(("Mixer %p (%d) is already stopped.", handle, handle->index));
1243        return;
1244    }
1245
1246    if ( !handle->startedExplicity )
1247    {
1248        BDBG_MSG(("Mixer %p (%d) was not started with BAPE_Mixer_Start(). Can't stop.", handle, handle->index));
1249        return;
1250    }
1251
1252    handle->startedExplicity = false;
1253    handle->running--;
1254   
1255    /* Stop the mixer task if nobody is running. */
1256    if ( 0 == handle->running && handle->task )
1257    {
1258        BDBG_MSG(("BAPE_DspMixer_P_Stop: Last running input has stopped - stop mixer task"));
1259        BAPE_DspMixer_P_StopTask(handle);
1260    }
1261           
1262    return;
1263}
1264
1265
1266static void BAPE_DspMixer_P_StopTask(BAPE_MixerHandle handle)
1267{
1268    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1269   
1270    if ( NULL == handle->task )
1271    {
1272        return;
1273    }
1274
1275    BDBG_ASSERT(0 == handle->running);
1276
1277    BDSP_Task_Stop(handle->task);
1278    BAPE_PathNode_P_StopPaths(&handle->pathNode);
1279    BDSP_Task_Destroy(handle->task);
1280    handle->task = NULL;
1281    BAPE_DspMixer_P_CleanupTaskCreateSettings(handle);
1282
1283    /* Unlink from PLL and give up FS if allocated */
1284    if ( handle->mclkSource != BAPE_MclkSource_eNone )
1285    {
1286        #if BAPE_CHIP_MAX_PLLS > 0
1287            if ( BAPE_MCLKSOURCE_IS_PLL(handle->mclkSource))
1288            {
1289                BAPE_P_DetachMixerFromPll(handle, handle->mclkSource - BAPE_MclkSource_ePll0);
1290            }
1291        #endif
1292        #if BAPE_CHIP_MAX_NCOS > 0
1293            if ( BAPE_MCLKSOURCE_IS_NCO(handle->mclkSource))
1294            {
1295                BAPE_P_DetachMixerFromNco(handle, handle->mclkSource - BAPE_MclkSource_eNco0);
1296            }
1297        #endif
1298
1299        handle->mclkSource = BAPE_MclkSource_eNone;
1300#if BAPE_CHIP_MAX_FS > 0
1301        BAPE_P_FreeFs(handle->deviceHandle, handle->fs);
1302        handle->fs = BAPE_FS_INVALID;
1303#endif
1304    }
1305}
1306
1307static void BAPE_DspMixer_P_CleanupTaskCreateSettings(BAPE_MixerHandle handle)
1308{
1309    unsigned i;
1310
1311    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1312
1313    /* The first branch is always static.  Others need to be BKNI_Free()'d. */
1314    /* This is not an ideal programming model, but workable */
1315    for ( i = 1; i < handle->taskCreateSettings.numBranches; i++ )
1316    {
1317        BDBG_ASSERT(NULL != handle->taskCreateSettings.pBranchInfo[i]);
1318        BKNI_Free(handle->taskCreateSettings.pBranchInfo[i]);
1319    }
1320    /* Reset structure to defaults */
1321    BDSP_Task_GetDefaultCreateSettings(handle->deviceHandle->dspContext, &handle->taskCreateSettings);
1322}
1323
1324static BERR_Code BAPE_DspMixer_P_AllocateLoopbackInput(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection)
1325{
1326    BERR_Code errCode;
1327    bool sfifo=false, buffers=false, buffersOnly=false;
1328    unsigned numChannelPairs, i;
1329
1330    BAPE_Connector input = pConnection->pSource;
1331
1332    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1333    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1334
1335    numChannelPairs = pConnection->pSource->numChannelPairs;
1336
1337    BDBG_MSG(("DSP Mixer %p Allocating resources for input %s %s", handle, input->pParent->pName, input->pName));
1338
1339    switch ( pConnection->pSource->dataSource )
1340    {
1341    case BAPE_DataSource_eDfifo:        /* Technically this could route directly to the DSP but it may require sample rate conversion */
1342    case BAPE_DataSource_eHostBuffer:
1343        sfifo = true;                   /* Playback via a Host Buffer requires a SFIFO allocation */
1344        buffers = pConnection->pSource->useBufferPool;
1345        break;
1346    case BAPE_DataSource_eFci:
1347        break;
1348    default:
1349        return BERR_TRACE(BERR_NOT_SUPPORTED);
1350    }
1351
1352    /* Check if we've already allocated resources */
1353    if ( pConnection->numChannelPairs > 0 )
1354    {
1355        if ( (pConnection->numChannelPairs == input->numChannelPairs) && (input->compressed == pConnection->compressed) &&
1356             (pConnection->ppmCorrection == pConnection->pSource->ppmCorrection) )
1357        {
1358            BDBG_MSG(("Connection %s -> %s %s already has the required resources", input->pParent->pName, pConnection->pSink->pName, input->pName));
1359            if ( sfifo )
1360            {
1361                BDBG_ASSERT(NULL != pConnection->sfifoGroup);
1362            }
1363            BDBG_ASSERT(NULL != pConnection->srcGroup);
1364            BDBG_ASSERT(NULL != pConnection->mixerGroup);
1365            BDBG_ASSERT(NULL != pConnection->loopbackGroup);
1366            BDBG_ASSERT(NULL != pConnection->dfifoGroup);
1367
1368            buffersOnly = true;
1369        }
1370        else
1371        {
1372            /* Connection format has changed */
1373            BDBG_MSG(("Connection %s -> %s %s format changed.  Releasing resources.", input->pParent->pName, pConnection->pSink->pName, input->pName));
1374            BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);
1375        }
1376    }
1377
1378    if ( buffers )
1379    {
1380        /* This is safe to call multiple times, it only allocates if need be */
1381        errCode = BAPE_P_AllocateInputBuffers(handle->deviceHandle, input);
1382        if ( errCode )
1383        {
1384            return BERR_TRACE(errCode);
1385        }
1386    }
1387
1388    if ( buffersOnly )
1389    {
1390        /* We don't need to re-add the remaining resources */
1391        return BERR_SUCCESS;
1392    }
1393
1394    pConnection->numChannelPairs = 0;
1395    pConnection->compressed = false;
1396    pConnection->ppmCorrection = false;
1397
1398    BDBG_ASSERT(NULL == pConnection->sfifoGroup);
1399    BDBG_ASSERT(NULL == pConnection->srcGroup);
1400
1401    /* Allocate SFIFO if required. */
1402    if ( sfifo )
1403    {
1404        if ( NULL == pConnection->sfifoGroup )
1405        {
1406            BAPE_SfifoGroupCreateSettings sfifoCreateSettings;
1407            BAPE_SfifoGroup_P_GetDefaultCreateSettings(&sfifoCreateSettings);
1408            sfifoCreateSettings.numChannelPairs = numChannelPairs;
1409            sfifoCreateSettings.ppmCorrection = false;
1410            errCode = BAPE_SfifoGroup_P_Create(handle->deviceHandle, &sfifoCreateSettings, &pConnection->sfifoGroup);
1411            if ( errCode )
1412            {
1413                (void)BERR_TRACE(errCode);
1414                goto err_alloc_sfifo;
1415            }
1416        }
1417    }
1418
1419    if ( NULL == pConnection->srcGroup )
1420    {
1421        BAPE_SrcGroupSettings srcSettings;
1422        BAPE_SrcGroupCreateSettings srcCreateSettings;
1423        BAPE_SrcGroup_P_GetDefaultCreateSettings(&srcCreateSettings);
1424        srcCreateSettings.numChannelPairs = numChannelPairs;
1425        errCode = BAPE_SrcGroup_P_Create(handle->deviceHandle, &srcCreateSettings, &pConnection->srcGroup);
1426        if ( errCode )
1427        {
1428            (void)BERR_TRACE(errCode);
1429            goto err_alloc_src;
1430        }
1431        /* Set SRC Linkage */
1432        BAPE_SrcGroup_P_GetSettings(pConnection->srcGroup, &srcSettings);
1433        if ( pConnection->sfifoGroup )
1434        {
1435            /* Input From Sfifo */
1436            BAPE_SfifoGroup_P_GetOutputFciIds(pConnection->sfifoGroup, &srcSettings.input);
1437        }
1438        else
1439        {
1440            /* Input from other FCI source */
1441            srcSettings.input = pConnection->inputFciGroup;
1442        }
1443        srcSettings.rampEnabled = false;            /* No need to ramp, output from the mixer will again be ramped. */
1444        srcSettings.startupRampEnabled = false;       
1445        errCode = BAPE_SrcGroup_P_SetSettings(pConnection->srcGroup, &srcSettings);
1446        if ( errCode )
1447        {
1448            errCode = BERR_TRACE(errCode);
1449            goto err_src_settings;
1450        }
1451    }
1452       
1453    if ( NULL == pConnection->mixerGroup )
1454    {
1455        BAPE_MixerGroupInputSettings mixerInputSettings;
1456        BAPE_MixerGroupCreateSettings mixerCreateSettings;
1457        BAPE_MixerGroup_P_GetDefaultCreateSettings(&mixerCreateSettings);
1458        mixerCreateSettings.numChannelPairs = numChannelPairs;
1459        errCode = BAPE_MixerGroup_P_Create(handle->deviceHandle, &mixerCreateSettings, &pConnection->mixerGroup);
1460        if ( errCode )
1461        {
1462            (void)BERR_TRACE(errCode);
1463            goto err_alloc_mixer;
1464        }
1465
1466        BAPE_MixerGroup_P_GetInputSettings(pConnection->mixerGroup, 0, &mixerInputSettings);
1467        BAPE_SrcGroup_P_GetOutputFciIds(pConnection->srcGroup, &mixerInputSettings.input);
1468        errCode = BAPE_MixerGroup_P_SetInputSettings(pConnection->mixerGroup, 0, &mixerInputSettings);
1469        if ( errCode )
1470        {
1471            (void)BERR_TRACE(errCode);
1472            goto err_mixer_input;
1473        }
1474    }
1475
1476    if ( NULL == pConnection->loopbackGroup )
1477    {
1478        BAPE_LoopbackGroupSettings loopbackSettings;
1479        BAPE_LoopbackGroupCreateSettings loopbackCreateSettings;
1480        BAPE_LoopbackGroup_P_GetDefaultCreateSettings(&loopbackCreateSettings);
1481        loopbackCreateSettings.numChannelPairs = numChannelPairs;
1482        errCode = BAPE_LoopbackGroup_P_Create(handle->deviceHandle, &loopbackCreateSettings, &pConnection->loopbackGroup);
1483        if ( errCode )
1484        {
1485            (void)BERR_TRACE(errCode);
1486            goto err_alloc_loopback;
1487        }
1488        BAPE_LoopbackGroup_P_GetSettings(pConnection->loopbackGroup, &loopbackSettings);
1489        /* FS will be set when task starts */
1490        BAPE_MixerGroup_P_GetOutputFciIds(pConnection->mixerGroup, 0, &loopbackSettings.input);
1491        loopbackSettings.resolution = 24;
1492        errCode = BAPE_LoopbackGroup_P_SetSettings(pConnection->loopbackGroup, &loopbackSettings);
1493        if ( errCode )
1494        {
1495            (void)BERR_TRACE(errCode);
1496            goto err_loopback_settings;
1497        }
1498    }
1499
1500    for ( i = 0; i < numChannelPairs; i++ )
1501    {
1502        if ( NULL == pConnection->pLoopbackBuffers[i] )
1503        {
1504            pConnection->pLoopbackBuffers[i] = BAPE_P_AllocateBuffer(handle->deviceHandle, BAPE_BufferType_ePcm);
1505            if ( NULL == pConnection->pLoopbackBuffers[i] )
1506            {
1507                errCode = BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
1508                goto err_buffer;
1509            }
1510        }
1511    }
1512
1513    if ( NULL == pConnection->dfifoGroup )
1514    {
1515        BAPE_DfifoGroupSettings dfifoSettings;
1516        BAPE_DfifoGroupCreateSettings dfifoCreateSettings;
1517        BAPE_DfifoGroup_P_GetDefaultCreateSettings(&dfifoCreateSettings);
1518        dfifoCreateSettings.numChannelPairs = numChannelPairs;
1519        errCode = BAPE_DfifoGroup_P_Create(handle->deviceHandle, &dfifoCreateSettings, &pConnection->dfifoGroup);
1520        if ( errCode )
1521        {
1522            (void)BERR_TRACE(errCode);
1523            goto err_alloc_dfifo;
1524        }
1525        BAPE_DfifoGroup_P_GetSettings(pConnection->dfifoGroup, &dfifoSettings);
1526        dfifoSettings.interleaveData = false;
1527        dfifoSettings.dataWidth = 32;
1528        BAPE_LoopbackGroup_P_GetCaptureFciIds(pConnection->loopbackGroup, &dfifoSettings.input);
1529        for ( i = 0; i < numChannelPairs; i++ )
1530        {
1531            uint32_t length;
1532            unsigned bufferNum = i*2;
1533            BAPE_BufferNode *pBuffer = pConnection->pLoopbackBuffers[i];
1534            length = pBuffer->bufferSize/2;
1535            dfifoSettings.bufferInfo[bufferNum].base = pBuffer->offset;
1536            dfifoSettings.bufferInfo[bufferNum+1].base = pBuffer->offset + length;
1537            dfifoSettings.bufferInfo[bufferNum].length = length;
1538            dfifoSettings.bufferInfo[bufferNum+1].length = length;
1539        }
1540        errCode = BAPE_DfifoGroup_P_SetSettings(pConnection->dfifoGroup, &dfifoSettings);
1541        if ( errCode )
1542        {
1543            (void)BERR_TRACE(errCode);
1544            goto err_dfifo_settings;
1545        }
1546    }
1547
1548    pConnection->numChannelPairs = numChannelPairs;
1549    pConnection->compressed = false;
1550    pConnection->ppmCorrection = false;
1551
1552    return BERR_SUCCESS;
1553
1554err_dfifo_settings:
1555err_alloc_dfifo:
1556err_buffer:
1557err_loopback_settings:
1558err_alloc_loopback:
1559err_mixer_input:
1560err_alloc_mixer:
1561err_src_settings:
1562err_alloc_src:
1563err_alloc_sfifo:
1564    BAPE_DspMixer_P_FreeConnectionResources(handle, pConnection);
1565    return errCode;
1566}
1567
1568static void BAPE_DspMixer_P_FreeConnectionResources(BAPE_MixerHandle handle, BAPE_PathConnection *pConnection)
1569{
1570    unsigned i;
1571
1572    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1573    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1574
1575    if ( NULL != pConnection->pInterTaskIoBuffer )
1576    {
1577        BMEM_Heap_Free(handle->deviceHandle->memHandle, pConnection->pInterTaskIoBuffer);
1578        pConnection->pInterTaskIoBuffer = NULL;
1579    }
1580    if ( NULL != pConnection->pInterTaskGenericBuffer )
1581    {
1582        BMEM_Heap_Free(handle->deviceHandle->memHandle, pConnection->pInterTaskGenericBuffer);
1583        pConnection->pInterTaskGenericBuffer = NULL;
1584    }
1585    if ( NULL != pConnection->pInterTaskIoDescriptor )
1586    {
1587        BMEM_Heap_Free(handle->deviceHandle->memHandle, pConnection->pInterTaskIoDescriptor);
1588        pConnection->pInterTaskIoDescriptor = NULL;
1589    }
1590    if ( NULL != pConnection->pInterTaskGenericDescriptor )
1591    {
1592        BMEM_Heap_Free(handle->deviceHandle->memHandle, pConnection->pInterTaskGenericDescriptor);
1593        pConnection->pInterTaskGenericDescriptor = NULL;
1594    }
1595    if ( pConnection->pSource->useBufferPool )
1596    {
1597        BAPE_P_FreeInputBuffers(handle->deviceHandle, pConnection->pSource);
1598    }
1599    if ( NULL != pConnection->sfifoGroup )
1600    {
1601        BAPE_SfifoGroup_P_Destroy(pConnection->sfifoGroup);
1602        pConnection->sfifoGroup = NULL;
1603    }
1604    if ( NULL != pConnection->srcGroup )
1605    {
1606        BAPE_SrcGroup_P_Destroy(pConnection->srcGroup);
1607        pConnection->srcGroup = NULL;
1608    }
1609    if ( NULL != pConnection->mixerGroup )
1610    {
1611        BAPE_MixerGroup_P_Destroy(pConnection->mixerGroup);
1612        pConnection->mixerGroup = NULL;
1613    }
1614    if ( NULL != pConnection->dfifoGroup )
1615    {
1616        BAPE_DfifoGroup_P_Destroy(pConnection->dfifoGroup);
1617        pConnection->dfifoGroup = NULL;
1618    }
1619    if ( NULL != pConnection->loopbackGroup )
1620    {
1621        BAPE_LoopbackGroup_P_Destroy(pConnection->loopbackGroup);
1622        pConnection->loopbackGroup = NULL;
1623    }
1624    for ( i = 0; i < BAPE_ChannelPair_eMax; i++ )
1625    {
1626        if ( NULL != pConnection->pLoopbackBuffers[i] )
1627        {
1628            BAPE_P_FreeBuffer(handle->deviceHandle, pConnection->pLoopbackBuffers[i]);
1629            pConnection->pLoopbackBuffers[i] = NULL;
1630        }
1631    }
1632
1633    pConnection->numChannelPairs = 0;       /* Required to force allocations next time */
1634    pConnection->ppmCorrection = false;
1635    pConnection->sampleRate = 0;   
1636}
1637
1638/* TODO: Share with other mixers */
1639static void BAPE_DspMixer_P_SetSampleRate_isr(BAPE_MixerHandle mixer, unsigned sampleRate)
1640{
1641    BDBG_OBJECT_ASSERT(mixer, BAPE_Mixer);
1642    /* Only do this if something actually changed */
1643    if ( mixer->sampleRate != sampleRate )
1644    {
1645        unsigned i;
1646
1647        BDBG_MSG(("Changing DSP mixer %p (%d) sample rate to %u [was %u]", mixer, mixer->index, sampleRate, mixer->sampleRate));
1648        mixer->sampleRate = sampleRate;
1649        for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
1650        {
1651            if ( mixer->inputs[i] )
1652            {
1653                BAPE_DspMixer_P_SetInputSRC_isr(mixer, mixer->inputs[i], mixer->inputs[i]->sampleRate, sampleRate);
1654            }
1655        }
1656
1657        #if BAPE_CHIP_MAX_PLLS > 0
1658        if ( BAPE_MCLKSOURCE_IS_PLL(mixer->mclkSource) && sampleRate != 0 )
1659        {
1660            BERR_Code errCode;
1661            /* Update the PLL */
1662            errCode = BAPE_P_UpdatePll_isr(mixer->deviceHandle, mixer->settings.outputPll);
1663            BDBG_ASSERT(errCode == BERR_SUCCESS);
1664        }
1665        #endif
1666
1667        #if BAPE_CHIP_MAX_NCOS > 0
1668        if ( BAPE_MCLKSOURCE_IS_NCO(mixer->mclkSource) && sampleRate != 0 )
1669        {
1670            BERR_Code errCode;
1671            /* Update the NCO */
1672            errCode = BAPE_P_UpdateNco_isr(mixer->deviceHandle, mixer->settings.outputNco);
1673            BDBG_ASSERT(errCode == BERR_SUCCESS);
1674        }
1675        #endif
1676
1677        if ( sampleRate != 0 )
1678        {           
1679            /* Propagate sample rate downstream */
1680            mixer->pathNode.paths[0].connector.sampleRate = sampleRate;
1681            BAPE_Connector_P_SampleRateChange_isr(&mixer->pathNode.paths[0].connector);
1682        }
1683    }
1684    else
1685    {
1686        BDBG_MSG(("NOT Changing DSP mixer %p (%d) sample rate to %u [currently %u]", mixer, mixer->index, sampleRate, mixer->sampleRate));
1687    }
1688}
1689
1690/* TODO: Share with other mixers */
1691static void BAPE_DspMixer_P_SetInputSRC_isr(BAPE_MixerHandle mixer, BAPE_Connector input, unsigned inputRate, unsigned outputRate)
1692{
1693    BAPE_PathConnection *pLink=NULL;
1694
1695    BDBG_OBJECT_ASSERT(mixer, BAPE_Mixer);
1696    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
1697
1698    /* Find connection node for this object */
1699    for ( pLink = BLST_SQ_FIRST(&input->connectionList);
1700          NULL != pLink;
1701          pLink = BLST_SQ_NEXT(pLink, downstreamNode) )
1702    {
1703        if ( pLink->pSink == &mixer->pathNode )
1704            break;
1705    }
1706    BDBG_ASSERT(NULL != pLink);
1707
1708    if ( pLink->srcGroup )
1709    {
1710        BDBG_MSG(("Setting input %s SRC to %u->%u", input->pName, inputRate, outputRate));
1711        BAPE_SrcGroup_P_SetSampleRate_isr(pLink->srcGroup, inputRate, outputRate);
1712    }
1713}
1714
1715/*************************************************************************/
1716static BERR_Code BAPE_DspMixer_P_GetInputVolume(
1717    BAPE_MixerHandle handle,
1718    BAPE_Connector input,
1719    BAPE_MixerInputVolume *pVolume      /* [out] */
1720    )
1721{
1722    unsigned i;
1723
1724    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1725    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
1726    BDBG_ASSERT(NULL != pVolume);
1727
1728    i = BAPE_Mixer_P_FindInputIndex(handle, input);
1729    if ( i == BAPE_MIXER_INPUT_INDEX_INVALID )
1730    {
1731        BDBG_ERR(("Input %p is not connected to mixer %p", input, handle));
1732        return BERR_TRACE(BERR_INVALID_PARAMETER);
1733    }
1734
1735    *pVolume = handle->inputVolume[i];
1736
1737    return BERR_SUCCESS;
1738}
1739
1740
1741
1742/*************************************************************************/
1743static BERR_Code BAPE_DspMixer_P_ApplyInputVolume(BAPE_MixerHandle mixer, unsigned index)
1744{
1745    BDSP_Raaga_Audio_MixerConfigParams userConfig;
1746    BAPE_Connector source = mixer->inputs[index];
1747    BERR_Code errCode;
1748    unsigned i, taskInputIndex;
1749    BAPE_PathConnection *pConnection;
1750
1751    BDBG_OBJECT_ASSERT(source, BAPE_PathConnector);
1752
1753    /* Make sure we have a valid input index */
1754    if ( index == BAPE_MIXER_INPUT_INDEX_INVALID )
1755    {
1756        return BERR_TRACE(BERR_INVALID_PARAMETER);
1757    }
1758
1759    /* Find Connection */
1760    pConnection = BAPE_Connector_P_GetConnectionToSink(mixer->inputs[index], &mixer->pathNode);
1761    if ( NULL == pConnection )
1762    {
1763        return BERR_TRACE(BERR_INVALID_PARAMETER);
1764    }
1765
1766    /* Input may not be running yet, check that. */
1767    if ( NULL == pConnection->taskInput )
1768    {
1769        return BERR_SUCCESS;
1770    }
1771
1772    /* Get task input index */
1773    errCode = BDSP_Task_GetStageInputIndex(pConnection->taskInput, &taskInputIndex);
1774    if ( errCode )
1775    {
1776        return BERR_TRACE(errCode);
1777    }
1778
1779    BDBG_ASSERT(taskInputIndex < BDSP_AF_P_MAX_IP_FORKS);
1780
1781    /* Apply settings to FW Mixer */
1782    errCode = BDSP_Task_GetStageSettings(mixer->task, 0, 0, &userConfig, sizeof(userConfig));
1783    if ( errCode )
1784    {
1785        return BERR_TRACE(errCode);
1786    }
1787
1788    for ( i = 0; i < BAPE_Channel_eMax; i++ )
1789    {
1790        uint32_t scaleValue;
1791       
1792        if ( mixer->inputVolume[index].muted || (i >= (mixer->inputs[index]->numChannelPairs*2)) )
1793        {
1794            scaleValue = 0;
1795        }
1796        else
1797        {
1798            scaleValue = mixer->inputVolume[index].coefficients[i][i];
1799            if ( scaleValue > 0x7FFFFFF )
1800            {
1801                BDBG_WRN(("Input coefficients out of range for input %s %s - saturating at 0x7FFFFFF", mixer->inputs[index]->pParent->pName, mixer->inputs[index]->pName));
1802                scaleValue = 0xFFFFFFFF;
1803            }
1804            else
1805            {
1806                scaleValue <<= 5;   /* Convert from 5.23 (HW) to 4.28 (DSP) */
1807            }
1808        }
1809        BDBG_MSG(("Setting FW Mixing Coefs[%u][%u] to 0x%08x (mute=%u value=%#x)", taskInputIndex, i, scaleValue, mixer->inputVolume[index].muted, mixer->inputVolume[index].coefficients[i][i]));
1810        userConfig.MixingCoeffs[taskInputIndex][i] = scaleValue;
1811    }
1812
1813    errCode = BDSP_Task_SetStageSettings(mixer->task, 0, 0, &userConfig, sizeof(userConfig));
1814    if ( errCode )
1815    {
1816        return BERR_TRACE(errCode);
1817    }
1818
1819    return BERR_SUCCESS;
1820}
1821
1822
1823/*************************************************************************/
1824static BERR_Code BAPE_DspMixer_P_SetInputVolume(
1825    BAPE_MixerHandle handle,
1826    BAPE_Connector input,
1827    const BAPE_MixerInputVolume *pVolume
1828    )
1829{
1830    unsigned i;
1831    BERR_Code errCode;
1832
1833    BDBG_OBJECT_ASSERT(handle, BAPE_Mixer);
1834    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
1835    BDBG_ASSERT(NULL != pVolume);
1836
1837    i = BAPE_Mixer_P_FindInputIndex(handle, input);
1838    if ( i == BAPE_MIXER_INPUT_INDEX_INVALID )
1839    {
1840        BDBG_ERR(("Input %p is not connected to mixer %p", input, handle));
1841        return BERR_TRACE(BERR_INVALID_PARAMETER);
1842    }
1843
1844    handle->inputVolume[i] = *pVolume;
1845    /* Apply volume if input is running */
1846    if ( handle->running )
1847    {
1848        errCode = BAPE_DspMixer_P_ApplyInputVolume(handle, i);
1849        if ( errCode )
1850        {
1851            return BERR_TRACE(errCode);
1852        }
1853    }
1854
1855    return BERR_SUCCESS;   
1856}
1857
1858#define NOT_SUPPORTED(x) NULL
1859/* If any of the APIs are not supported by a particular type of mixer,
1860 * just add a placeholder like this:
1861 *   NOT_SUPPORTED(BAPE_DspMixer_P_RemoveAllInputs)
1862 */
1863
1864static const BAPE_MixerInterface g_dspMixerInterface = {
1865    BAPE_DspMixer_P_Destroy,
1866    BAPE_DspMixer_P_Start,
1867    BAPE_DspMixer_P_Stop,
1868    BAPE_DspMixer_P_AddInput,
1869    BAPE_DspMixer_P_RemoveInput,
1870    BAPE_DspMixer_P_RemoveAllInputs,
1871    NOT_SUPPORTED(BAPE_DspMixer_P_AddOutput),
1872    NOT_SUPPORTED(BAPE_DspMixer_P_RemoveOutput),
1873    NOT_SUPPORTED(BAPE_DspMixer_P_RemoveAllOutputs),
1874    BAPE_DspMixer_P_GetInputVolume,
1875    BAPE_DspMixer_P_SetInputVolume,
1876    NOT_SUPPORTED(BAPE_DspMixer_P_ApplyOutputVolume),
1877    NOT_SUPPORTED(BAPE_DspMixer_P_SetSettings)
1878};
1879
Note: See TracBrowser for help on using the repository browser.