source: svn/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_dp_priv.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: 60.0 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_dp_priv.c $
11 * $brcm_Revision: Hydra_Software_Devel/13 $
12 * $brcm_Date: 2/23/12 10:53a $
13 *
14 * Module Description: Audio PI Device Level Interface
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/ape/7422/bape_dp_priv.c $
19 *
20 * Hydra_Software_Devel/13   2/23/12 10:53a jgarrett
21 * SW7405-5003: Removing BKNI_Memcmp where structures aren't copied with
22 * BKNI_Memcpy
23 *
24 * Hydra_Software_Devel/12   2/22/12 10:17a gskerl
25 * SW7425-2094: Added initialization code to disable volume ramp at zero
26 * crossing. This will insure that volume ramping happens at each sample.
27 *
28 * Hydra_Software_Devel/11   1/9/12 5:39p jgarrett
29 * SW7425-2097: Correcting mixer input address on 7429
30 *
31 * Hydra_Software_Devel/10   11/15/11 6:38p gskerl
32 * SW7429-18: Removed a couple of #warnings that were leftover from a
33 * previous merge.
34 *
35 * Hydra_Software_Devel/9   11/14/11 3:42p gskerl
36 * SW7429-18: Merging 7429 changes back to main branch.
37 *
38 * Hydra_Software_Devel/SW7429-18/2   11/8/11 11:22a gskerl
39 * SW7429-18: Fixed sanity check for ping coefficients regOffset.
40 *
41 * Hydra_Software_Devel/SW7429-18/1   10/21/11 6:29p jgarrett
42 * SW7429-18: Initial compileable version for 7429
43 *
44 * Hydra_Software_Devel/8   11/1/11 2:43p gskerl
45 * SW7425-1647: Changed default OutputVolumeRampStep from 0x10000 to
46 * 0xA00.
47 *
48 * Hydra_Software_Devel/7   11/1/11 2:34p gskerl
49 * SW7231-129: Added power standby/resume support for
50 * OutputVolumeRampStep.
51 *
52 * Hydra_Software_Devel/6   9/16/11 6:52p gskerl
53 * SW7231-129: Refactored to put hardware and software initialization into
54 * separate functions.
55 *
56 * Hydra_Software_Devel/5   5/13/11 4:14p jgarrett
57 * SW7425-212: Fixing multichannel DP output mute handling
58 *
59 * Hydra_Software_Devel/4   5/4/11 4:07p jgarrett
60 * SW7425-469: Enabling only connected output channel pairs.  Resolves bug
61 * where 5.1 PCM is unstable for HDMI since the channel status formatter
62 * only takes one channel pair as input instead of 3
63 *
64 * Hydra_Software_Devel/3   4/16/11 12:15p jgarrett
65 * SW7425-371: Removing tab characters
66 *
67 * Hydra_Software_Devel/2   4/12/11 5:34p jgarrett
68 * SW7425-292: Fixing input mute and preserving output mute across
69 * start/stop
70 *
71 * Hydra_Software_Devel/1   4/6/11 1:24a jgarrett
72 * SW35330-35: Merge to main branch
73 *
74 * Hydra_Software_Devel/SW35330-35/2   4/5/11 7:14p jgarrett
75 * SW35330-35: PCM Playback working on 35230
76 *
77 * Hydra_Software_Devel/SW35330-35/1   4/5/11 12:50p jgarrett
78 * SW35330-35: FMM Abstraction refactoring to support DTV
79 *
80 ***************************************************************************/
81
82#include "bstd.h"
83#include "bkni.h"
84#include "bape.h"
85#include "bape_priv.h"
86#include "bchp_aud_fmm_dp_ctrl0.h"
87
88BDBG_MODULE(bape_dp_priv);
89
90#define BAPE_PLAYBACK_ID_INVALID (0xffffffff)
91
92#define BAPE_MIXER_DEFAULT_RAMP_STEP (0xa00)
93#define BAPE_DP_MAX_RAMP_STEP (0x07FFFFFF)
94
95/***************************************************************************
96Summary:
97Mixer Group
98***************************************************************************/
99typedef struct BAPE_MixerGroup
100{
101    bool allocated;
102    uint8_t blockId;
103    unsigned numChannelPairs;
104    BAPE_Handle deviceHandle;
105    uint32_t mixerIds[BAPE_ChannelPair_eMax];
106    unsigned numRunningInputs;
107    struct
108    {
109        BAPE_MixerGroupInputSettings settings;
110        unsigned numChannelPairs;
111        uint32_t playbackIds[BAPE_ChannelPair_eMax];
112        bool started;
113        bool linked;
114    } inputs[BAPE_CHIP_MAX_MIXER_INPUTS];
115    unsigned numRunningOutputs;
116    struct
117    {
118        BAPE_MixerGroupOutputSettings settings;     
119        bool started;
120    } outputs[BAPE_CHIP_MAX_MIXER_OUTPUTS];
121    BAPE_MixerGroupSettings settings;
122} BAPE_MixerGroup;
123
124
125static void BAPE_DpMixer_P_SetGroup(BAPE_Handle deviceHandle, uint32_t mixerId, uint32_t groupId);
126static void BAPE_DpMixer_P_LoadInputCoefs(BAPE_Handle deviceHandle, uint32_t mixerId, unsigned inputIndex, 
127                                          uint32_t leftToLeft, uint32_t rightToLeft, uint32_t leftToRight, uint32_t rightToRight);
128static void BAPE_DpMixer_P_LoadOutputCoefs(BAPE_Handle deviceHandle, uint32_t mixerId, unsigned outputIndex, uint32_t left, uint32_t right);
129
130static BERR_Code BAPE_MixerGroup_P_LinkInput(BAPE_MixerGroupHandle handle, unsigned inputIndex);
131static void BAPE_MixerGroup_P_UnlinkInput(BAPE_MixerGroupHandle handle, unsigned inputIndex);
132static void BAPE_MixerGroup_P_ApplyInputCoefficients(BAPE_MixerGroupHandle handle, unsigned inputIndex);
133static void BAPE_MixerGroup_P_ApplyOutputCoefficients(BAPE_MixerGroupHandle handle, unsigned outputIndex);
134static uint32_t BAPE_DpMixer_P_GetConfigAddress(unsigned mixerId);
135static uint32_t BAPE_DpMixer_P_GetInputConfigAddress(unsigned mixerId, unsigned inputId);
136
137/***************************************************************************
138Summary:
139Initialize the DP block data structures
140***************************************************************************/
141BERR_Code BAPE_P_InitDpSw(
142    BAPE_Handle handle
143    )
144{
145    unsigned i;
146
147    BDBG_OBJECT_ASSERT(handle, BAPE_Device);
148
149    /* TODO: Register for ESR's to catch HW Failures?? */
150
151    /* Setup Group Handles */
152    BDBG_MSG(("Allocating %u MIXER Groups", BAPE_CHIP_MAX_MIXER_GROUPS));
153    handle->mixerGroups[0] = BKNI_Malloc(BAPE_CHIP_MAX_MIXER_GROUPS*sizeof(BAPE_MixerGroup));
154    if ( NULL == handle->mixerGroups[0] )
155    {
156        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
157    }
158    BKNI_Memset(handle->mixerGroups[0], 0, BAPE_CHIP_MAX_MIXER_GROUPS*sizeof(BAPE_MixerGroup));
159    for ( i = 1; i < BAPE_CHIP_MAX_MIXER_GROUPS; i++ )
160    {
161        handle->mixerGroups[i] = handle->mixerGroups[0] + i;
162    }
163
164    /* Set the default ramp step value. */
165    handle->outputVolumeRampStep = BAPE_MIXER_DEFAULT_RAMP_STEP;
166
167    return BERR_SUCCESS;
168}
169
170/***************************************************************************
171Summary:
172Initialize the DP block
173***************************************************************************/
174BERR_Code BAPE_P_InitDpHw(
175    BAPE_Handle handle
176    )
177{
178    uint32_t regAddr;
179    BREG_Handle regHandle;
180    unsigned i, j;
181
182    BDBG_OBJECT_ASSERT(handle, BAPE_Device);
183
184    regHandle = handle->regHandle;
185
186    BDBG_MSG(("Clearing all DP registers"));
187
188    for ( i = 0; i < BAPE_CHIP_MAX_MIXERS; i++ )
189    {
190        BAPE_DpMixer_P_SetGroup(handle, i, i);
191        for ( j = 0; j < BAPE_CHIP_MAX_MIXER_INPUTS; j++ )
192        {
193            BAPE_DpMixer_P_LoadInputCoefs(handle, i, j, 0, 0, 0, 0);
194        }
195        for ( j = 0; j < BAPE_CHIP_MAX_MIXER_OUTPUTS; j++ )
196        {
197            BAPE_DpMixer_P_LoadOutputCoefs(handle, i, j, 0, 0);
198        }
199        /* Make sure to disable the "volume ramp at zero cross" setting (if it exists). */
200        regAddr = BAPE_DpMixer_P_GetConfigAddress(i);
201        #if defined BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG_DISABLE_VOL_RAMP_AT_ZERO_CROSS_MASK
202                BAPE_Reg_P_UpdateEnum(handle, regAddr, AUD_FMM_DP_CTRL0_MIXER0_CONFIG, DISABLE_VOL_RAMP_AT_ZERO_CROSS, Disable);
203        #elif defined BCHP_AUD_FMM_DP_CTRL0_MIXER_CONFIGi
204                BAPE_Reg_P_UpdateEnum(handle, regAddr, AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOL_RAMP_AT_ZERO_CROSS_ENA, Disable);
205        #endif
206    }
207
208#ifdef BCHP_AUD_FMM_DP_CTRL0_PING_COEFF_RAMP_STEPi_ARRAY_BASE
209    regAddr = BCHP_AUD_FMM_DP_CTRL0_PING_COEFF_RAMP_STEPi_ARRAY_BASE;
210    for ( i=BCHP_AUD_FMM_DP_CTRL0_PING_COEFF_RAMP_STEPi_ARRAY_START; i<=BCHP_AUD_FMM_DP_CTRL0_PING_COEFF_RAMP_STEPi_ARRAY_END; i++ )
211    {
212        BREG_Write32(regHandle, regAddr, BAPE_MIXER_DEFAULT_RAMP_STEP);
213        regAddr += 4;
214    }
215#else
216    BREG_Write32(regHandle, BCHP_AUD_FMM_DP_CTRL0_PING_COEFF_RAMP_STEP, BAPE_MIXER_DEFAULT_RAMP_STEP);
217#endif
218#ifdef BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE
219#ifdef BCHP_AUD_FMM_DP_CTRL0_PONG_COEFF_RAMP_STEPi_ARRAY_BASE
220    regAddr = BCHP_AUD_FMM_DP_CTRL0_PONG_COEFF_RAMP_STEPi_ARRAY_BASE;
221    for ( i=BCHP_AUD_FMM_DP_CTRL0_PONG_COEFF_RAMP_STEPi_ARRAY_START; i<=BCHP_AUD_FMM_DP_CTRL0_PONG_COEFF_RAMP_STEPi_ARRAY_END; i++ )
222    {
223        BREG_Write32(regHandle, regAddr, BAPE_MIXER_DEFAULT_RAMP_STEP);
224        regAddr += 4;
225    }
226#else
227    BREG_Write32(regHandle, BCHP_AUD_FMM_DP_CTRL0_PONG_COEFF_RAMP_STEP, BAPE_MIXER_DEFAULT_RAMP_STEP);
228#endif
229#endif
230
231    BDBG_MSG(("Setting RAMP STEP to %lu", handle->outputVolumeRampStep));
232    (void)BAPE_SetOutputVolumeRampStep(handle, handle->outputVolumeRampStep);
233
234   /* Init Playback FCI ID's to Invalid */
235    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_PLAYBACKS; i++ )
236    {
237        regAddr = BCHP_AUD_FMM_DP_CTRL0_PB_FCI_IDi_ARRAY_BASE + 4*(i); 
238        BREG_Write32(regHandle, regAddr, BAPE_FCI_ID_INVALID);
239    }
240
241    /* TODO: Register for ESR's to catch HW Failures?? */
242
243    return BERR_SUCCESS;
244}
245
246/***************************************************************************
247Summary:
248Un-Initialize the DP block
249***************************************************************************/
250void BAPE_P_UninitDpSw(
251    BAPE_Handle handle
252    )
253{
254    if ( handle->mixerGroups[0] )
255    {
256        BKNI_Free(handle->mixerGroups[0]);
257        BKNI_Memset(handle->mixerGroups, 0, sizeof(handle->mixerGroups));
258    }
259}
260
261static void BAPE_DpMixer_P_SetGroup(
262    BAPE_Handle deviceHandle, 
263    uint32_t mixerId, 
264    uint32_t groupId
265    )
266{
267    uint32_t regAddr, regVal;
268    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
269    regAddr = BAPE_DpMixer_P_GetConfigAddress(mixerId);
270    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
271#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG
272    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, MIXER_GROUP_BEGIN);
273    regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, MIXER_GROUP_BEGIN, groupId);
274#else
275    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, MIXER_GROUP_BEGIN);
276    regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, MIXER_GROUP_BEGIN, groupId);   
277#endif
278    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
279}
280
281void BAPE_MixerGroup_P_GetDefaultCreateSettings(
282    BAPE_MixerGroupCreateSettings *pSettings    /* [out] */
283    )
284{
285    BDBG_ASSERT(NULL != pSettings);
286    pSettings->numChannelPairs = 1;
287    pSettings->blockId = 0;
288}
289
290BERR_Code BAPE_MixerGroup_P_Create(
291    BAPE_Handle deviceHandle,
292    const BAPE_MixerGroupCreateSettings *pSettings,
293    BAPE_MixerGroupHandle *pHandle  /* [out] */
294    )
295{
296    BERR_Code errCode;
297    unsigned i, j, mixer;
298    BAPE_MixerGroupHandle handle=NULL;
299
300    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
301    BDBG_ASSERT(NULL != pSettings);
302    BDBG_ASSERT(NULL != pHandle);
303    BDBG_ASSERT(pSettings->numChannelPairs <= BAPE_ChannelPair_eMax);
304    BDBG_ASSERT(pSettings->blockId == 0);   /* TODO: Handle more than one */
305
306    /* Find an available group handle */
307    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_GROUPS; i++ )
308    {
309        BDBG_ASSERT(NULL != deviceHandle->mixerGroups[i]);
310        if ( !deviceHandle->mixerGroups[i]->allocated )
311        {
312            handle = deviceHandle->mixerGroups[i];
313            break;
314        }
315    }
316
317    /* If none found, return error */
318    if ( NULL == handle )
319    {
320        return BERR_TRACE(BERR_NOT_SUPPORTED);
321    }
322
323    /* Now search for the correct number of resources */
324    errCode = BAPE_P_AllocateFmmResource(deviceHandle, BAPE_FmmResourceType_eMixer, pSettings->numChannelPairs, &mixer);
325    if ( errCode )
326    {
327        errCode = BERR_TRACE(errCode);
328        goto err_alloc_mixer;
329    }
330
331    /* Successfully allocated resources.  Initialize Group */
332    BKNI_Memset(handle, 0, sizeof(BAPE_MixerGroup));
333    handle->allocated = true;
334    handle->blockId = pSettings->blockId;
335    handle->numChannelPairs = pSettings->numChannelPairs;
336    handle->deviceHandle = deviceHandle;
337    handle->settings.volumeControlEnabled = true;
338    BKNI_Memset(handle->mixerIds, 0xff, sizeof(handle->mixerIds));
339    for ( i = 0; i < pSettings->numChannelPairs; i++ )
340    {
341        handle->mixerIds[i] = mixer + i;
342        /* Setup Grouping */
343        BAPE_DpMixer_P_SetGroup(deviceHandle, mixer + i, mixer);
344    }
345    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
346    {
347        BAPE_FciIdGroup_Init(&handle->inputs[i].settings.input);
348        for ( j = 0; j < pSettings->numChannelPairs; j++ )
349        {
350            handle->inputs[i].settings.coefficients[j][0][0] = BAPE_VOLUME_NORMAL;
351            handle->inputs[i].settings.coefficients[j][1][1] = BAPE_VOLUME_NORMAL;
352        }
353        BKNI_Memset(handle->inputs[i].playbackIds, 0xff, sizeof(handle->inputs[i].playbackIds));
354    }
355    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_OUTPUTS; i++ )
356    {
357        for ( j = 0; j < 2*pSettings->numChannelPairs; j++ )
358        {
359            handle->outputs[i].settings.coefficients[j] = BAPE_VOLUME_NORMAL;
360        }
361    }
362
363    *pHandle = handle;
364    return BERR_SUCCESS;
365
366    err_alloc_mixer:
367    return errCode; 
368}
369
370
371void BAPE_MixerGroup_P_Destroy(
372    BAPE_MixerGroupHandle handle
373    )
374{
375    unsigned i;
376
377    BDBG_ASSERT(NULL != handle);
378    BDBG_ASSERT(handle->allocated);
379
380    BDBG_ASSERT(handle->numRunningInputs == 0);
381    BDBG_ASSERT(handle->numRunningOutputs == 0);
382
383    /* Make sure we release all playbacks to the pool */
384    for ( i = 0; i < BAPE_CHIP_MAX_MIXER_INPUTS; i++ )
385    {
386        if ( handle->inputs[i].linked )
387        {
388            BAPE_MixerGroup_P_UnlinkInput(handle, i);
389        }
390    }
391
392    /* Make sure Mixer Group ID's are reset to un-grouped */
393    for ( i = 0; i < handle->numChannelPairs; i++ )
394    {
395        BAPE_DpMixer_P_SetGroup(handle->deviceHandle, handle->mixerIds[i], handle->mixerIds[i]);
396    }
397
398    /* Release Resources */
399    BAPE_P_FreeFmmResource(handle->deviceHandle, BAPE_FmmResourceType_eMixer, handle->numChannelPairs, handle->mixerIds[0]);
400    BKNI_Memset(handle->mixerIds, 0xff, sizeof(handle->mixerIds));
401
402    /* Done */
403    handle->allocated = false;
404}
405
406void BAPE_MixerGroup_P_GetSettings(
407    BAPE_MixerGroupHandle handle,
408    BAPE_MixerGroupSettings *pSettings  /* [out] */
409    )
410{
411    BDBG_ASSERT(NULL != handle);
412    BDBG_ASSERT(handle->allocated);
413    *pSettings = handle->settings;
414}
415
416BERR_Code BAPE_MixerGroup_P_SetSettings(
417    BAPE_MixerGroupHandle handle,
418    const BAPE_MixerGroupSettings *pSettings
419    )
420{
421    BDBG_ASSERT(NULL != handle);
422    BDBG_ASSERT(handle->allocated);
423
424    /* Soft Limiting is not currently supported */
425    if ( pSettings->softLimitEnabled )
426    {
427        return BERR_TRACE(BERR_NOT_SUPPORTED);
428    }
429
430    if ( handle->numRunningOutputs > 0 )
431    {
432        uint32_t regVal, regAddr;
433        unsigned i;
434        /* Support changing VOLUME_ENA on the fly.  Others do not change. */
435        for ( i = 0; i < handle->numChannelPairs; i++ )
436        {
437            regAddr = BAPE_DpMixer_P_GetConfigAddress(handle->mixerIds[i]);
438            regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
439#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG
440            regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_ENA);
441            regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_ENA, pSettings->volumeControlEnabled?1:0);
442#else
443            regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_ENA);
444            regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_ENA, pSettings->volumeControlEnabled?1:0);
445#endif
446            BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
447        }       
448    }
449    handle->settings = *pSettings;
450
451    return BERR_SUCCESS;
452}
453
454void BAPE_MixerGroup_P_GetInputSettings(
455    BAPE_MixerGroupHandle handle,
456    unsigned inputIndex,
457    BAPE_MixerGroupInputSettings *pSettings  /* [out] */
458    )
459{
460    BDBG_ASSERT(NULL != handle);
461    BDBG_ASSERT(handle->allocated);
462    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
463    BDBG_ASSERT(NULL != pSettings);
464
465    *pSettings = handle->inputs[inputIndex].settings;
466}
467
468static bool BAPE_MixerGroup_P_CoefficientsChanged(const BAPE_MixerGroupInputSettings *pSettings1, const BAPE_MixerGroupInputSettings *pSettings2)
469{
470    unsigned i,j;
471
472    BDBG_ASSERT(NULL != pSettings1);
473    BDBG_ASSERT(NULL != pSettings2);
474
475    for ( i = 0; i < BAPE_Channel_eMax; i++ )
476    {
477        for ( j = 0; j < BAPE_Channel_eMax; j++ )
478        {
479            if ( pSettings1->coefficients[i][j] != pSettings2->coefficients[i][j] )
480            {
481                return true;
482            }
483        }
484    }
485
486    return false;
487}
488
489BERR_Code BAPE_MixerGroup_P_SetInputSettings(
490    BAPE_MixerGroupHandle handle,
491    unsigned inputIndex,
492    const BAPE_MixerGroupInputSettings *pSettings
493    )
494{
495    BERR_Code errCode;
496    unsigned numInputPairs=0;
497    bool inputChanged = false;
498    BDBG_ASSERT(NULL != handle);
499    BDBG_ASSERT(handle->allocated);
500    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
501    BDBG_ASSERT(NULL != pSettings);
502
503    if ( handle->inputs[inputIndex].started )
504    {
505        /* We can't change FCI ID while running - only check volume */
506        if ( BAPE_MixerGroup_P_CoefficientsChanged(&handle->inputs[inputIndex].settings, pSettings) )
507        {
508            /* Coefficients have changed.  Copy and update. */
509            BKNI_Memcpy(handle->inputs[inputIndex].settings.coefficients, pSettings->coefficients, sizeof(pSettings->coefficients));
510            BAPE_MixerGroup_P_ApplyInputCoefficients(handle, inputIndex);
511        }
512        return BERR_SUCCESS;
513    }
514
515    /* If not started, we need to check for an input change */
516    if ( !BAPE_FciIdGroup_IsEqual(handle->inputs[inputIndex].settings.input, pSettings->input) )
517    {
518        /* Make sure new FCI ID Group is legal */
519        numInputPairs = BAPE_FciIdGroup_GetNumChannelPairs(pSettings->input);
520        if ( numInputPairs > handle->numChannelPairs )
521        {
522            BDBG_ERR(("Input %u has more channel pairs (%u) than mixers in the group (%u).", inputIndex, numInputPairs, handle->numChannelPairs));
523            return BERR_TRACE(BERR_INVALID_PARAMETER);
524        }
525        if ( handle->inputs[inputIndex].linked )
526        {
527            BAPE_MixerGroup_P_UnlinkInput(handle, inputIndex);
528        }
529        inputChanged = true;
530    }
531
532    /* Update stored settings */
533    handle->inputs[inputIndex].settings = *pSettings;
534
535    /* Setup Playback Binding if Required */
536    if ( inputChanged )
537    {
538        handle->inputs[inputIndex].numChannelPairs = numInputPairs;
539        if ( numInputPairs > 0 )
540        {
541            errCode = BAPE_MixerGroup_P_LinkInput(handle, inputIndex);
542            if ( errCode )
543            {
544                /* Likely unable to retrieve resources.  Reset Stored FCI ID to default. */
545                BAPE_FciIdGroup_Init(&handle->inputs[inputIndex].settings.input);
546                handle->inputs[inputIndex].numChannelPairs = 0;
547                return BERR_TRACE(errCode);
548            }
549        }
550    }
551
552    return BERR_SUCCESS;
553}
554
555static BERR_Code BAPE_MixerGroup_P_LinkInput(
556    BAPE_MixerGroupHandle handle, 
557    unsigned inputIndex
558    )
559{
560    unsigned i, j, playback=(unsigned)-1;
561    BAPE_FciId firstFci;
562    BAPE_Handle deviceHandle;
563    BERR_Code errCode;
564    uint32_t regAddr;
565
566    BDBG_ASSERT(NULL != handle);
567    BDBG_ASSERT(handle->allocated);
568    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
569
570    deviceHandle = handle->deviceHandle;
571    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
572
573    /* Make sure Free was previously called */
574    BDBG_ASSERT(handle->inputs[inputIndex].linked == false);
575
576    /* Check for no input */
577    if ( handle->inputs[inputIndex].numChannelPairs == 0 )
578    {
579        return BERR_TRACE(BERR_INVALID_PARAMETER);
580    }
581
582    /* Determine if FCI ID's are already used by another playback */
583    firstFci = handle->inputs[inputIndex].settings.input.ids[0];
584    for ( i = 0; i <= (BAPE_CHIP_MAX_MIXER_PLAYBACKS-(handle->inputs[inputIndex].numChannelPairs)); i++ )
585    {
586        if ( deviceHandle->playbackReferenceCount[i] > 0 &&
587             deviceHandle->playbackFci[i] == firstFci )
588        {
589            /* We have found a match.  Sanity check that other group members are also present or we have an
590               unrecoverable failure.  */
591            for ( j = 1; j < handle->inputs[inputIndex].numChannelPairs; j++ )
592            {
593                if ( deviceHandle->playbackReferenceCount[i+j] == 0 ||
594                     deviceHandle->playbackFci[i+j] != handle->inputs[inputIndex].settings.input.ids[j] )
595                {
596                    BDBG_ERR(("FCI ID %#x is already in use by DP Playback %u but does not follow proper grouping.", firstFci));
597                    return BERR_TRACE(BERR_NOT_SUPPORTED);
598                }
599            }
600
601            playback = i;
602            goto update_reference_counts;
603        }
604    }
605
606    /* If we reach here, we didn't find a playback already in use.  Allocate a new set. */
607    errCode = BAPE_P_AllocateFmmResource(deviceHandle, BAPE_FmmResourceType_ePlayback, handle->inputs[inputIndex].numChannelPairs, &playback);
608    if ( errCode )
609    {
610        return BERR_TRACE(errCode);
611    }
612
613    update_reference_counts:
614    /* Update Reference Counts */
615    for ( j = 0; j < handle->inputs[inputIndex].numChannelPairs; j++ )
616    {
617        handle->inputs[inputIndex].playbackIds[j] = playback+j;
618        if ( 0 == deviceHandle->playbackReferenceCount[playback+j] )
619        {
620            regAddr = BCHP_AUD_FMM_DP_CTRL0_PB_FCI_IDi_ARRAY_BASE + 4*(playback+j);
621            BREG_Write32(deviceHandle->regHandle, regAddr, handle->inputs[inputIndex].settings.input.ids[j]);
622            deviceHandle->playbackFci[playback+j] = handle->inputs[inputIndex].settings.input.ids[j];
623
624        }
625        deviceHandle->playbackReferenceCount[playback+j]++;
626    }
627    handle->inputs[inputIndex].linked = true;
628
629    return BERR_SUCCESS;
630}
631
632static void BAPE_MixerGroup_P_UnlinkInput(
633    BAPE_MixerGroupHandle handle, 
634    unsigned inputIndex
635    )
636{
637    unsigned i;
638    uint32_t regAddr;
639    BAPE_Handle deviceHandle;
640
641    BDBG_ASSERT(NULL != handle);
642    BDBG_ASSERT(handle->allocated);
643    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
644
645    deviceHandle = handle->deviceHandle;
646    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
647
648    /* Make sure Free was not previously called and we're not releasing a running resource */
649    BDBG_ASSERT(handle->inputs[inputIndex].linked == true);
650    BDBG_ASSERT(handle->inputs[inputIndex].started == false);
651
652    for ( i = 0; i < handle->inputs[inputIndex].numChannelPairs; i++ )
653    {
654        unsigned playback = handle->inputs[inputIndex].playbackIds[i];
655        /* If this is the last user of the playback, we will need to free it. */
656        if ( deviceHandle->playbackReferenceCount[playback] == 1 )
657        {
658            /* Free this playback */
659            BAPE_P_FreeFmmResource(handle->deviceHandle, BAPE_FmmResourceType_ePlayback, 1, playback);
660            regAddr = BCHP_AUD_FMM_DP_CTRL0_PB_FCI_IDi_ARRAY_BASE + 4*(playback+i);
661            deviceHandle->playbackFci[playback] = BAPE_FCI_ID_INVALID;
662            BREG_Write32(deviceHandle->regHandle, regAddr, BAPE_FCI_ID_INVALID);
663        }
664        deviceHandle->playbackReferenceCount[playback]--;
665    }
666    handle->inputs[inputIndex].linked = false;
667}
668
669BERR_Code BAPE_MixerGroup_P_StartInput(
670    BAPE_MixerGroupHandle handle,
671    unsigned inputIndex
672    )
673{
674    unsigned i;
675    BAPE_Handle deviceHandle;
676    uint32_t regVal, regAddr;
677
678    BDBG_ASSERT(NULL != handle);
679    BDBG_ASSERT(handle->allocated);
680    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
681
682    deviceHandle = handle->deviceHandle;
683    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
684
685    /* Make sure Free was not previously called and we're not starting twice */
686    BDBG_ASSERT(handle->inputs[inputIndex].linked == true);
687    BDBG_ASSERT(handle->inputs[inputIndex].started == false);
688
689    /* Setup Input Linkage */
690    for ( i = 0; i < handle->numChannelPairs; i++ )
691    {
692        uint32_t pbId;
693
694        /* Handle "Type1 vs Type2 - see MIXER_GROUP_BEGIN field in RDB docs */
695        pbId = (i < handle->inputs[inputIndex].numChannelPairs)?handle->inputs[inputIndex].playbackIds[i]:handle->inputs[inputIndex].playbackIds[handle->inputs[inputIndex].numChannelPairs-1];
696
697        /* Correlate mixer ID to register base */
698        regAddr = BAPE_DpMixer_P_GetInputConfigAddress(handle->mixerIds[i], inputIndex);
699        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
700
701#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG
702        if ( (inputIndex % 2) == 0 )
703        {
704            regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG, MIXER_INPUT0_PB_NUMBER);
705            regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG, MIXER_INPUT0_PB_NUMBER, pbId);
706        }
707        else
708        {
709            regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG, MIXER_INPUT1_PB_NUMBER);
710            regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG, MIXER_INPUT1_PB_NUMBER, pbId);
711        }
712#else
713        regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT_CONFIGi, MIXER_INPUT_PB_NUMBER);
714        regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER0_INPUT_CONFIGi, MIXER_INPUT_PB_NUMBER, pbId);
715#endif
716
717        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);     
718    }
719
720    /* Apply Group-Level Settings */
721    for ( i = 0; i < handle->numChannelPairs; i++ )
722    {
723#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG
724        /* Volume -- Add soft limit here also if later required. */
725        regAddr = BAPE_DpMixer_P_GetConfigAddress(handle->mixerIds[i]);
726        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
727        regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_ENA);
728        regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_ENA, handle->settings.volumeControlEnabled?1:0);
729        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
730        /* Priority */
731    #ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER_HIGH_PRIORITY
732        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER_HIGH_PRIORITY;
733        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
734        regVal &= ~(BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_HIGH_PRIORITY, MIXER0_HIGH_PRIORITY)<<handle->mixerIds[i]);
735        regVal |= (BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_HIGH_PRIORITY, MIXER0_HIGH_PRIORITY, handle->settings.highPriority?1:0)<<handle->mixerIds[i]);
736        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
737    #else
738        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA;
739        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
740        regVal &= ~(BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA, MIXER0_HIGH_PRIORITY)<<handle->mixerIds[i]);
741        regVal |= (BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA, MIXER0_HIGH_PRIORITY, handle->settings.highPriority?1:0)<<handle->mixerIds[i]);
742        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
743    #endif
744#else
745        /* New 7429-style mixer combines these bits in the config register */
746        regAddr = BAPE_DpMixer_P_GetConfigAddress(handle->mixerIds[i]);
747        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
748        regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_ENA);
749        regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_ENA, handle->settings.volumeControlEnabled?1:0);
750        regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, MIXER_HIGH_PRIORITY);
751        regVal |= (BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, MIXER_HIGH_PRIORITY, handle->settings.highPriority?1:0)<<handle->mixerIds[i]);
752        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);       
753#endif
754    }           
755
756    /* Apply Input Scaling Coefs */
757    BAPE_MixerGroup_P_ApplyInputCoefficients(handle, inputIndex);
758
759    /* Enable the mixer input */
760    for ( i = 0; i < handle->numChannelPairs; i++ )
761    {
762        uint32_t bitmask;
763
764        /* Find input config register (they are paired) */
765        regAddr = BAPE_DpMixer_P_GetInputConfigAddress(handle->mixerIds[i], inputIndex);
766
767#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG
768        if ( 0 == (inputIndex%2) )
769        {
770            /* Even.  Write the first enable. */
771            bitmask = BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG, MIXER_INPUT0_ENA);
772        }
773        else
774        {
775            /* Odd.  Write the second enable. */
776            bitmask = BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG, MIXER_INPUT1_ENA);
777        }
778#else
779        bitmask = BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT_CONFIGi, MIXER_INPUT_ENA);
780#endif
781
782        BDBG_MSG(("Enabling mixer %u input port %u (PB %u FCI %u)", handle->mixerIds[i], inputIndex,
783                  handle->inputs[inputIndex].playbackIds[i], 
784                  handle->deviceHandle->playbackFci[handle->inputs[inputIndex].playbackIds[i]]));
785        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
786        regVal |= bitmask;
787        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);     
788    }
789
790    handle->inputs[inputIndex].started = true;
791    handle->numRunningInputs++;
792    BDBG_MSG(("Mixer Group %#x now has %u running inputs", handle, handle->numRunningInputs));
793
794    return BERR_SUCCESS;
795}
796
797void BAPE_MixerGroup_P_StopInput(
798    BAPE_MixerGroupHandle handle,
799    unsigned inputIndex
800    )
801{
802    unsigned i;
803    BAPE_Handle deviceHandle;
804    uint32_t regVal, regAddr;
805
806    BDBG_ASSERT(NULL != handle);
807    BDBG_ASSERT(handle->allocated);
808    BDBG_ASSERT(inputIndex < BAPE_CHIP_MAX_MIXER_INPUTS);
809
810    deviceHandle = handle->deviceHandle;
811    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
812
813    /* Make sure Free was not previously called and we're not stopping twice */
814    BDBG_ASSERT(handle->inputs[inputIndex].linked == true);
815    if ( false == handle->inputs[inputIndex].started )
816    {
817        return;
818    }
819
820    /* Disable the mixer input */
821    for ( i = 0; i < handle->numChannelPairs; i++ )
822    {
823        uint32_t bitmask;
824
825        /* Find input config register */
826        regAddr = BAPE_DpMixer_P_GetInputConfigAddress(handle->mixerIds[i], inputIndex);
827#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG
828        if ( 0 == (inputIndex%2) )
829        {
830            /* Even.  Write the first enable. */
831            bitmask = BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG, MIXER_INPUT0_ENA);
832        }
833        else
834        {
835            /* Odd.  Write the second enable. */
836            bitmask = BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG, MIXER_INPUT1_ENA);
837        }
838#else
839        bitmask = BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_INPUT_CONFIGi, MIXER_INPUT_ENA);
840#endif
841        BDBG_MSG(("Disabling mixer %u input port %u (PB %u FCI %u)", handle->mixerIds[i], inputIndex,
842                  handle->inputs[inputIndex].playbackIds[i], 
843                  handle->deviceHandle->playbackFci[handle->inputs[inputIndex].playbackIds[i]]));
844        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
845        regVal &= ~bitmask;
846        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);     
847    }
848
849    handle->inputs[inputIndex].started = false;
850    BDBG_ASSERT(handle->numRunningInputs > 0);
851    handle->numRunningInputs--; 
852}
853
854void BAPE_MixerGroup_P_GetOutputSettings(
855    BAPE_MixerGroupHandle handle,
856    unsigned outputIndex,
857    BAPE_MixerGroupOutputSettings *pSettings  /* [out] */
858    )
859{
860    BDBG_ASSERT(NULL != handle);
861    BDBG_ASSERT(handle->allocated);
862    BDBG_ASSERT(outputIndex < BAPE_CHIP_MAX_MIXER_OUTPUTS);
863    BDBG_ASSERT(NULL != pSettings);
864    *pSettings = handle->outputs[outputIndex].settings;
865}
866
867BERR_Code BAPE_MixerGroup_P_SetOutputSettings(
868    BAPE_MixerGroupHandle handle,
869    unsigned outputIndex,
870    const BAPE_MixerGroupOutputSettings *pSettings
871    )
872{
873    BDBG_ASSERT(NULL != handle);
874    BDBG_ASSERT(handle->allocated);
875    BDBG_ASSERT(outputIndex < BAPE_CHIP_MAX_MIXER_OUTPUTS);
876    BDBG_ASSERT(NULL != pSettings);
877
878    handle->outputs[outputIndex].settings = *pSettings;
879
880    if ( handle->outputs[outputIndex].started )
881    {
882        BAPE_MixerGroup_P_ApplyOutputCoefficients(handle, outputIndex);
883    }
884
885    return BERR_SUCCESS;
886}
887
888void BAPE_MixerGroup_P_GetOutputStatus(
889    BAPE_MixerGroupHandle handle,
890    unsigned outputIndex,
891    BAPE_MixerGroupOutputStatus *pStatus    /* [out] */
892    )
893{
894    unsigned i;
895    BDBG_ASSERT(NULL != handle);
896    BDBG_ASSERT(handle->allocated);
897    BDBG_ASSERT(outputIndex < BAPE_CHIP_MAX_MIXER_OUTPUTS);
898    BDBG_ASSERT(NULL != pStatus);
899
900    BKNI_Memset(pStatus, 0, sizeof(BAPE_MixerGroupOutputStatus));
901    if ( handle->outputs[outputIndex].started )
902    {
903        uint32_t rampStatus, regAddr;
904
905#ifdef BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS0
906        /* Read back ramp status from mixer */
907        regAddr = (outputIndex == 0) ? BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS0 : BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS1;
908        rampStatus = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
909
910        for ( i = 0; i < handle->numChannelPairs; i++ )
911        {
912            uint32_t bitmask;
913            bitmask = BCHP_MASK(AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS0, MIXER0_LEFT_VOLUME_RAMP) << handle->mixerIds[i];
914            pStatus->rampActive[2*i] = (rampStatus & bitmask) ? true : false;
915            bitmask = BCHP_MASK(AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS0, MIXER0_RIGHT_VOLUME_RAMP) << handle->mixerIds[i];
916            pStatus->rampActive[(2*i)+1] = (rampStatus & bitmask) ? true : false;
917        }
918#else       
919        regAddr = BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUSi_ARRAY_BASE + ((BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUSi_ARRAY_ELEMENT_SIZE/8)*outputIndex);
920        rampStatus = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
921
922        for ( i = 0; i < handle->numChannelPairs; i++ )
923        {
924            uint32_t bitmask;
925            bitmask = (outputIndex == 0) ? 
926                BCHP_MASK(AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUSi, MIXER_OUTPUT0_LEFT_VOLUME_RAMP) :
927                BCHP_MASK(AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUSi, MIXER_OUTPUT1_LEFT_VOLUME_RAMP);
928            pStatus->rampActive[2*i] = (rampStatus & bitmask) ? true : false;
929            bitmask = (outputIndex == 0) ? 
930                BCHP_MASK(AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUSi, MIXER_OUTPUT0_RIGHT_VOLUME_RAMP) :
931                BCHP_MASK(AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUSi, MIXER_OUTPUT1_RIGHT_VOLUME_RAMP);
932            pStatus->rampActive[(2*i)+1] = (rampStatus & bitmask) ? true : false;
933        }
934#endif
935    }
936}
937
938BERR_Code BAPE_MixerGroup_P_StartOutput(
939    BAPE_MixerGroupHandle handle,
940    unsigned outputIndex
941    )
942{
943    unsigned i, outputChannelPairs;
944    uint32_t regAddr, regVal, bitmask;
945
946    BDBG_ASSERT(NULL != handle);
947    BDBG_ASSERT(handle->allocated);
948    BDBG_ASSERT(outputIndex < BAPE_CHIP_MAX_MIXER_OUTPUTS);
949    BDBG_ASSERT(handle->outputs[outputIndex].started == false);
950
951    /* Refresh output scaling coefficients first */
952    BAPE_MixerGroup_P_ApplyOutputCoefficients(handle, outputIndex);
953
954    /* Start */
955    if ( handle->outputs[outputIndex].settings.numChannelPairs == 0 )
956    {
957        outputChannelPairs = handle->numChannelPairs;
958    }
959    else
960    {
961        outputChannelPairs = handle->outputs[outputIndex].settings.numChannelPairs;
962    }
963    for ( i = 0; i < outputChannelPairs; i++ )
964    {
965        /* Start mixer output */
966#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA
967        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA;
968        bitmask = (0 == outputIndex) ?
969                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA, MIXER0_OUTPUT0_ENA) :
970                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA, MIXER0_OUTPUT1_ENA);
971
972        BDBG_MSG(("Enabling mixer %u output port %u", handle->mixerIds[i], outputIndex));
973        bitmask <<= handle->mixerIds[i];
974        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
975        regVal |= bitmask;
976        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
977#else
978        regAddr = BAPE_DpMixer_P_GetConfigAddress(handle->mixerIds[i]);
979        bitmask = (0 == outputIndex) ?
980                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, MIXER_OUTPUT0_ENA) :
981                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, MIXER_OUTPUT1_ENA);
982
983        BDBG_MSG(("Enabling mixer %u output port %u", handle->mixerIds[i], outputIndex));
984        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
985        regVal |= bitmask;
986        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
987#endif
988    }
989
990    handle->outputs[outputIndex].started = true;
991    handle->numRunningOutputs++;
992
993    return BERR_SUCCESS;
994}
995
996void BAPE_MixerGroup_P_StopOutput(
997    BAPE_MixerGroupHandle handle,
998    unsigned outputIndex
999    )
1000{
1001    unsigned i;
1002    uint32_t regAddr, regVal, bitmask;
1003
1004    BDBG_ASSERT(NULL != handle);
1005    BDBG_ASSERT(handle->allocated);
1006    BDBG_ASSERT(outputIndex < BAPE_CHIP_MAX_MIXER_OUTPUTS);
1007    if ( handle->outputs[outputIndex].started == false )
1008    {
1009        return;
1010    }
1011
1012    /* Stop */
1013    for ( i = 0; i < handle->numChannelPairs; i++ )
1014    {
1015        /* Stop mixer output */
1016#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA
1017        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA;
1018        bitmask = (0 == outputIndex) ?
1019                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA, MIXER0_OUTPUT0_ENA) :
1020                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT_ENA, MIXER0_OUTPUT1_ENA);
1021
1022        BDBG_MSG(("Disabling mixer %u output port %u", handle->mixerIds[i], outputIndex));
1023        bitmask <<= handle->mixerIds[i];
1024        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1025        regVal &= ~bitmask;
1026        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1027#else
1028        regAddr = BAPE_DpMixer_P_GetConfigAddress(handle->mixerIds[i]);
1029        bitmask = (0 == outputIndex) ?
1030                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, MIXER_OUTPUT0_ENA) :
1031                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, MIXER_OUTPUT1_ENA);
1032
1033        BDBG_MSG(("Disabling mixer %u output port %u", handle->mixerIds[i], outputIndex));
1034        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1035        regVal &= ~bitmask;
1036        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1037#endif
1038    }
1039
1040    handle->outputs[outputIndex].started = false;
1041    BDBG_ASSERT(handle->numRunningOutputs > 0);
1042    handle->numRunningOutputs--;
1043}
1044
1045void BAPE_MixerGroup_P_GetOutputFciIds(
1046    BAPE_MixerGroupHandle handle,
1047    unsigned outputIndex,
1048    BAPE_FciIdGroup *pFciGroup      /* [out] */
1049    )
1050{
1051    unsigned i;
1052
1053    BDBG_ASSERT(NULL != handle);
1054    BDBG_ASSERT(handle->allocated);
1055    BDBG_ASSERT(outputIndex < BAPE_CHIP_MAX_MIXER_OUTPUTS);
1056    BDBG_ASSERT(NULL != pFciGroup);
1057
1058    BAPE_FciIdGroup_Init(pFciGroup);
1059
1060    for ( i = 0; i < handle->numChannelPairs; i++ )
1061    {
1062        pFciGroup->ids[i] = ((0x4<<6)|(handle->mixerIds[i]*BAPE_CHIP_MAX_MIXER_OUTPUTS)|outputIndex);
1063    }
1064}
1065
1066static void BAPE_DpMixer_P_LoadInputCoefs(
1067    BAPE_Handle deviceHandle, 
1068    uint32_t mixerId, 
1069    unsigned inputIndex, 
1070    uint32_t left0, 
1071    uint32_t right0, 
1072    uint32_t left1, 
1073    uint32_t right1
1074    )
1075{
1076    uint32_t regVal, regAddr, regOffset;
1077    uint32_t mixerNum, portNum;
1078
1079    mixerNum = mixerId;
1080    portNum = inputIndex;
1081
1082#ifdef BCHP_AUD_FMM_DP_CTRL0_USE_NEW_SCALING_COEFF
1083    /* On chips without a ping/pong setup - program the mixer to freeze the coefficients while updating */
1084    regVal = BREG_Read32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_USE_NEW_SCALING_COEFF);
1085    regVal &= ~(1<<mixerNum);
1086    BREG_Write32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_USE_NEW_SCALING_COEFF, regVal);
1087#endif
1088
1089    /* -- From the RDB for 7408: (Same for other chips except for number of mixers, inputs, and coefficients)
1090    Lout = Left_Coef_0 * Lin + Right_Coef_0 * Rin;;;;  Rout = Left_Coef_1 * Lin + Right_Coef_1 * Rin.
1091    For input M of mixer N (where M ranges from 0 to 3 and N are ranges from 0 to 5), the index to the scaling coefficient array is at follow:
1092    Left_Coef_0 = coef[N*16 + M*4 + 0], Right_Coef_0 = coef[N*16 + M*4 + 1];;;;  Left_Coef_1 = coef[N*16 + M*4 + 2], Right_Coef_1 = coef[N*16 + M*4 + 3],
1093    For example, the scaling coefficients for input 0 of mixer 0 are
1094    Left_Coef_0 = coef[0], Right_Coef_0 = coef[1];;;;  Left_Coef_1 = coef[2], Right_Coef_1 = coef[3].
1095    The scaling coefficients for input 3 of mixer 1 are
1096    Left_Coef_0 = coef[28], Right_Coef_0 = coef[29];;;;  Left_Coef_1 = coef[30], Right_Coef_1 = coef[31].
1097    */
1098
1099    /* Compute left coefficient 0 offset */
1100    regOffset = (mixerNum * 4 * BAPE_CHIP_MAX_MIXER_INPUTS) + (portNum * 4);
1101    BDBG_ASSERT(regOffset <= (BCHP_AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi_ARRAY_END-3));   /* Sanity check */
1102    regAddr = (regOffset * 4) + BCHP_AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi_ARRAY_BASE;
1103    regVal = left0 & BCHP_MASK(AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi, COEFFICIENTS);
1104    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1105#ifdef BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE
1106    /* Write pong coef also */
1107    BDBG_CASSERT(BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE > BCHP_AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi_ARRAY_BASE);
1108    BREG_Write32(deviceHandle->regHandle, regAddr + (BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE-BCHP_AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi_ARRAY_BASE), regVal);
1109#endif
1110
1111    regAddr += 4;   /* Jump to Right_Coef_0 */
1112    regVal = right0 & BCHP_MASK(AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi, COEFFICIENTS);
1113    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1114#ifdef BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE
1115    /* Write pong coef also */
1116    BREG_Write32(deviceHandle->regHandle, regAddr + (BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE-BCHP_AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi_ARRAY_BASE), regVal);
1117#endif
1118
1119    regAddr += 4;   /* Jump to Left_Coef_1 */
1120    regVal = left1 & BCHP_MASK(AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi, COEFFICIENTS);
1121    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1122#ifdef BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE
1123    /* Write pong coef also */
1124    BREG_Write32(deviceHandle->regHandle, regAddr + (BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE-BCHP_AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi_ARRAY_BASE), regVal);
1125#endif
1126
1127    regAddr += 4;   /* Jump to Right_Coef_1 */
1128    regVal = right1 & BCHP_MASK(AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi, COEFFICIENTS);
1129    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1130#ifdef BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE
1131    /* Write pong coef also */
1132    BREG_Write32(deviceHandle->regHandle, regAddr + (BCHP_AUD_FMM_DP_CTRL0_PONG_COEFFICIENTSi_ARRAY_BASE-BCHP_AUD_FMM_DP_CTRL0_PING_COEFFICIENTSi_ARRAY_BASE), regVal);
1133#endif
1134
1135#ifdef BCHP_AUD_FMM_DP_CTRL0_USE_NEW_SCALING_COEFF
1136    /* On chips without a ping/pong setup - program the mixer to load the coefficients after updating */
1137    regVal = BREG_Read32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_USE_NEW_SCALING_COEFF);
1138    regVal |= (1<<mixerNum);
1139    BREG_Write32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_USE_NEW_SCALING_COEFF, regVal);
1140#endif
1141}
1142
1143static void BAPE_MixerGroup_P_ApplyInputCoefficients(
1144    BAPE_MixerGroupHandle handle, 
1145    unsigned inputIndex
1146    )
1147{
1148    unsigned i;
1149    int32_t leftToLeft, rightToLeft, leftToRight, rightToRight;
1150
1151    for ( i = 0; i < handle->numChannelPairs; i++ )
1152    {
1153        /* For now, cloned input channel pairs when input res < output res to be zero.
1154           If need be, these could be passed from the caller instead */
1155        if ( handle->inputs[inputIndex].numChannelPairs < i )
1156        {
1157            leftToLeft = 0;
1158            rightToLeft = 0;
1159            leftToRight = 0;
1160            rightToRight = 0;
1161        }
1162        else
1163        {
1164            /* Index by [Channel Pair][input channel][output channel] */
1165            leftToLeft = handle->inputs[inputIndex].settings.coefficients[i][0][0];
1166            rightToLeft = handle->inputs[inputIndex].settings.coefficients[i][1][0];
1167            leftToRight = handle->inputs[inputIndex].settings.coefficients[i][0][1];
1168            rightToRight = handle->inputs[inputIndex].settings.coefficients[i][1][1];
1169        }
1170        BAPE_DpMixer_P_LoadInputCoefs(handle->deviceHandle, handle->mixerIds[i], inputIndex, 
1171                                      leftToLeft, rightToLeft, leftToRight, rightToRight);
1172    }
1173}
1174
1175static void BAPE_DpMixer_P_LoadOutputCoefs(
1176    BAPE_Handle deviceHandle, 
1177    uint32_t mixerId, 
1178    unsigned outputIndex, 
1179    uint32_t left, 
1180    uint32_t right
1181    )
1182{
1183    uint32_t regAddr, regVal;
1184
1185#if defined BCHP_AUD_FMM_DP_CTRL0_MIXER00_0_RT_VOL_LEVEL
1186    const uint32_t rightRegOffset = BCHP_AUD_FMM_DP_CTRL0_MIXER00_0_RT_VOL_LEVEL-BCHP_AUD_FMM_DP_CTRL0_MIXER00_0_LT_VOL_LEVEL;
1187    const uint32_t mixerRegOffset = BCHP_AUD_FMM_DP_CTRL0_MIXER01_0_LT_VOL_LEVEL-BCHP_AUD_FMM_DP_CTRL0_MIXER00_0_LT_VOL_LEVEL;
1188
1189    if ( 1 == outputIndex )
1190    {
1191        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER00_1_LT_VOL_LEVEL;
1192    }
1193    else
1194    {
1195        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER00_0_LT_VOL_LEVEL;
1196    }
1197
1198    left = BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER00_0_LT_VOL_LEVEL, MIXER_OUTPUT_LEFT_VOLUME_LEVEL, left) &
1199           BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER00_0_LT_VOL_LEVEL, MIXER_OUTPUT_LEFT_VOLUME_LEVEL);
1200    right = BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER00_0_RT_VOL_LEVEL, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL, right) &
1201            BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER00_0_RT_VOL_LEVEL, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL);
1202
1203    regAddr += mixerRegOffset * ((uint32_t) mixerId);
1204    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1205    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER00_0_LT_VOL_LEVEL, MIXER_OUTPUT_LEFT_VOLUME_LEVEL);           
1206    regVal |= left;
1207    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1208
1209    regAddr += rightRegOffset;
1210    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1211    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER00_0_RT_VOL_LEVEL, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL);
1212    regVal |= right;
1213    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1214#elif defined BCHP_AUD_FMM_DP_CTRL0_MIXER00_RT_VOL_LEVEL
1215    const uint32_t rightRegOffset = BCHP_AUD_FMM_DP_CTRL0_MIXER00_RT_VOL_LEVEL-BCHP_AUD_FMM_DP_CTRL0_MIXER00_LT_VOL_LEVEL;
1216    const uint32_t mixerRegOffset = BCHP_AUD_FMM_DP_CTRL0_MIXER10_LT_VOL_LEVEL-BCHP_AUD_FMM_DP_CTRL0_MIXER00_LT_VOL_LEVEL;
1217
1218    if ( 1 == outputIndex )
1219    {
1220        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER01_LT_VOL_LEVEL;
1221    }
1222    else
1223    {
1224        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER00_LT_VOL_LEVEL;
1225    }
1226
1227    left = BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER00_LT_VOL_LEVEL, MIXER_OUTPUT_LEFT_VOLUME_LEVEL, left) &
1228           BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER00_LT_VOL_LEVEL, MIXER_OUTPUT_LEFT_VOLUME_LEVEL);
1229    right = BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER00_RT_VOL_LEVEL, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL, right) &
1230            BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER00_RT_VOL_LEVEL, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL);
1231
1232    regAddr += mixerRegOffset * ((uint32_t) mixerId);
1233    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1234    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER00_LT_VOL_LEVEL, MIXER_OUTPUT_LEFT_VOLUME_LEVEL);           
1235    regVal |= left;
1236    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1237
1238    regAddr += rightRegOffset;
1239    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1240    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER00_RT_VOL_LEVEL, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL);
1241    regVal |= right;
1242    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1243#elif defined BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_LT_VOL_LEVELi_ARRAY_BASE
1244    const uint32_t rightRegOffset = BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_RT_VOL_LEVELi_ARRAY_BASE - BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_LT_VOL_LEVELi_ARRAY_BASE;
1245    const uint32_t mixerRegOffset = BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_RT_VOL_LEVELi_ARRAY_ELEMENT_SIZE/8;
1246
1247    if ( 1 == outputIndex )
1248    {
1249        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT1_LT_VOL_LEVELi_ARRAY_BASE;
1250    }
1251    else
1252    {
1253        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_LT_VOL_LEVELi_ARRAY_BASE;
1254    }
1255
1256    left = BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_LT_VOL_LEVELi, MIXER_OUTPUT_LEFT_VOLUME_LEVEL, left) &
1257           BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_LT_VOL_LEVELi, MIXER_OUTPUT_LEFT_VOLUME_LEVEL);
1258    right = BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_RT_VOL_LEVELi, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL, right) &
1259            BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_RT_VOL_LEVELi, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL);
1260
1261    regAddr += mixerRegOffset * ((uint32_t) mixerId);
1262    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1263    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_LT_VOL_LEVELi, MIXER_OUTPUT_LEFT_VOLUME_LEVEL);           
1264    regVal |= left;
1265    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1266
1267    regAddr += rightRegOffset;
1268    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1269    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_OUTPUT0_RT_VOL_LEVELi, MIXER_OUTPUT_RIGHT_VOLUME_LEVEL);
1270    regVal |= right;
1271    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);   
1272#else
1273#error Mixer output volume registers undefined
1274#endif
1275}
1276
1277static void BAPE_MixerGroup_P_ApplyOutputCoefficients(
1278    BAPE_MixerGroupHandle handle, 
1279    unsigned outputIndex
1280    )
1281{
1282    bool wasMuted;
1283    unsigned i;
1284    uint32_t configRegVal, configRegAddr, bitmask;
1285#if !(defined BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG_VOLUME_RAMP_DISABLE_OUTPUT0_MASK || defined BCHP_AUD_FMM_DP_CTRL0_MIXER_CONFIGi_VOLUME_RAMP_ENA_OUTPUT0_MASK)
1286    uint32_t oldRampStep=0;
1287#endif
1288
1289    /* Cases to be handled.  */
1290    /* Mute -> Unmute - Load Coefs first, then unmute so mixer ramps properly. */
1291    /* Unmute -> Mute - Set Mute First, starts ramping immediately.  Then set coefs. */
1292    /* Unmute -> Unmute (change in coefs only) */
1293
1294#if !(defined BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG_VOLUME_RAMP_DISABLE_OUTPUT0_MASK || defined BCHP_AUD_FMM_DP_CTRL0_MIXER_CONFIGi_VOLUME_RAMP_ENA_OUTPUT0_MASK)
1295    /* Ugh.  No direct support for disabling output ramp.  Need to spin while any pending ramp is going on, jam the ramp step to max, change vol, restore */
1296    if ( handle->outputs[outputIndex].settings.volumeRampDisabled )
1297    {
1298        unsigned timeout=1000;
1299        /* Spin for all pending ramps to finish */
1300        while ( (BREG_Read32(handle->deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS0) |
1301                 BREG_Read32(handle->deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS1)) &&
1302                timeout > 0 )
1303        {
1304            BDBG_MSG(("Waiting for ramp to complete..."));
1305            BKNI_Sleep(1);
1306            timeout--;
1307        }
1308        /* Set max ramp step value */
1309        BAPE_GetOutputVolumeRampStep(handle->deviceHandle, &oldRampStep);
1310        BAPE_SetOutputVolumeRampStep(handle->deviceHandle, BAPE_DP_MAX_RAMP_STEP);
1311    }
1312#endif
1313
1314    for ( i = 0; i < handle->numChannelPairs; i++ )
1315    {
1316        /* Get Current Mute Status */
1317        configRegAddr = BAPE_DpMixer_P_GetConfigAddress(handle->mixerIds[i]);
1318        configRegVal = BREG_Read32(handle->deviceHandle->regHandle, configRegAddr);
1319#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG
1320        bitmask = (outputIndex == 0) ?
1321                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_MUTE_ENA_OUTPUT0):
1322                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_MUTE_ENA_OUTPUT1);
1323#else
1324        bitmask = (outputIndex == 0) ?
1325                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_MUTE_ENA_OUTPUT0):
1326                  BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_MUTE_ENA_OUTPUT1);
1327#endif
1328        wasMuted = (configRegVal & bitmask) ? true : false;
1329
1330        /* Handle Ramp Disable First */
1331#if defined BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG_VOLUME_RAMP_DISABLE_OUTPUT0_MASK
1332        /* Sweet, the mixer supports it on a per-output basis. */
1333        if ( outputIndex == 0 )
1334        {
1335            configRegVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_RAMP_DISABLE_OUTPUT0);
1336            configRegVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_RAMP_DISABLE_OUTPUT0, handle->outputs[outputIndex].settings.volumeRampDisabled?1:0);
1337        }
1338        else
1339        {
1340            configRegVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_RAMP_DISABLE_OUTPUT1);
1341            configRegVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER0_CONFIG, VOLUME_RAMP_DISABLE_OUTPUT1, handle->outputs[outputIndex].settings.volumeRampDisabled?1:0);
1342        }
1343#elif defined BCHP_AUD_FMM_DP_CTRL0_MIXER_CONFIGi_VOLUME_RAMP_ENA_OUTPUT0_MASK
1344        /* Sweet, the mixer supports it on a per-output basis. */
1345        if ( outputIndex == 0 )
1346        {
1347            configRegVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_RAMP_ENA_OUTPUT0);
1348            configRegVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_RAMP_ENA_OUTPUT0, handle->outputs[outputIndex].settings.volumeRampDisabled?0:1);
1349        }
1350        else
1351        {
1352            configRegVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_RAMP_ENA_OUTPUT0);
1353            configRegVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_MIXER_CONFIGi, VOLUME_RAMP_ENA_OUTPUT0, handle->outputs[outputIndex].settings.volumeRampDisabled?0:1);
1354        }       
1355#endif
1356
1357        /* Determine if we're going to mute and if so do that first to start the ramp. */
1358        if ( !wasMuted && handle->outputs[outputIndex].settings.muted )
1359        {
1360            configRegVal |= bitmask;
1361        }
1362
1363        /* Update config register with any changes */
1364        BREG_Write32(handle->deviceHandle->regHandle, configRegAddr, configRegVal);
1365
1366        /* Now set coefficients */
1367        BAPE_DpMixer_P_LoadOutputCoefs(handle->deviceHandle, handle->mixerIds[i], outputIndex, 
1368                                       handle->outputs[outputIndex].settings.coefficients[2*i],
1369                                       handle->outputs[outputIndex].settings.coefficients[(2*i)+1]);
1370
1371        /* Done with coefficients.  Now Unmute if we need to. */
1372        if ( !handle->outputs[outputIndex].settings.muted )
1373        {
1374            configRegVal &= ~bitmask;
1375            BREG_Write32(handle->deviceHandle->regHandle, configRegAddr, configRegVal);
1376        }
1377    }
1378
1379    /* Restore ramp step if required. */
1380#if !(defined BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG_VOLUME_RAMP_DISABLE_OUTPUT0_MASK || defined BCHP_AUD_FMM_DP_CTRL0_MIXER_CONFIGi_VOLUME_RAMP_ENA_OUTPUT0_MASK)
1381    if ( handle->outputs[outputIndex].settings.volumeRampDisabled )
1382    {
1383        unsigned timeout=1000;
1384        /* Spin for all pending ramps to finish (should be a NOP with max ramp step) */
1385        while ( (BREG_Read32(handle->deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS0) |
1386                 BREG_Read32(handle->deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STATUS1)) &&
1387                timeout > 0 )
1388        {
1389            BDBG_MSG(("Waiting for ramp to complete to allow ramp step to be restored..."));
1390            BKNI_Sleep(1);
1391            timeout--;
1392        }
1393        /* Restore original value */
1394        BAPE_SetOutputVolumeRampStep(handle->deviceHandle, oldRampStep);
1395    }
1396#endif
1397}
1398
1399void BAPE_GetOutputVolumeRampStep(
1400    BAPE_Handle deviceHandle,
1401    uint32_t *pRampStep                 /* All mixers output output volume is changed by this amount
1402                                                                            every Fs while ramping.  Specified in 4.23 format.
1403                                                                            Ignored for compressed data. */
1404    )
1405{
1406    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1407    BDBG_ASSERT(NULL != pRampStep);
1408
1409    *pRampStep = deviceHandle->outputVolumeRampStep;
1410    return;
1411}
1412
1413BERR_Code BAPE_SetOutputVolumeRampStep(
1414    BAPE_Handle deviceHandle,
1415    uint32_t rampStep                   /* All mixers output output volume is changed by this amount
1416                                                                                 every Fs while ramping.  Specified in 4.23 format.
1417                                                                                 Ignored for compressed data. */
1418    )
1419{
1420    uint32_t regVal;
1421    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1422
1423#if defined BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_UP_STEP
1424    regVal = BREG_Read32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_UP_STEP);
1425    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_VOLUME_RAMP_UP_STEP, VOLUME_RAMP_UP_STEP);
1426    regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_VOLUME_RAMP_UP_STEP, VOLUME_RAMP_UP_STEP, rampStep);
1427    BREG_Write32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_UP_STEP, regVal);
1428    BREG_Write32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_DOWN_STEP, regVal);
1429
1430    /* Save the setting in the BAPE_Device struct.  Use the value from the register field in case the user's value was truncated. */
1431    deviceHandle->outputVolumeRampStep = BCHP_GET_FIELD_DATA(regVal, AUD_FMM_DP_CTRL0_VOLUME_RAMP_UP_STEP, VOLUME_RAMP_UP_STEP);
1432
1433#elif defined BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STEP
1434    regVal = BREG_Read32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STEP);
1435    regVal &= ~BCHP_MASK(AUD_FMM_DP_CTRL0_VOLUME_RAMP_STEP, VOLUME_RAMP_STEP);
1436    regVal |= BCHP_FIELD_DATA(AUD_FMM_DP_CTRL0_VOLUME_RAMP_STEP, VOLUME_RAMP_STEP, rampStep);
1437    BREG_Write32(deviceHandle->regHandle, BCHP_AUD_FMM_DP_CTRL0_VOLUME_RAMP_STEP, regVal);
1438
1439    /* Save the setting in the BAPE_Device struct.  Use the value from the register field in case the user's value was truncated. */
1440    deviceHandle->outputVolumeRampStep = BCHP_GET_FIELD_DATA(regVal, AUD_FMM_DP_CTRL0_VOLUME_RAMP_STEP, VOLUME_RAMP_STEP);
1441
1442#else
1443#error Mixer output ramp step not defined
1444#endif
1445    return BERR_SUCCESS;
1446}
1447
1448static uint32_t BAPE_DpMixer_P_GetConfigAddress(
1449    unsigned mixerId
1450    )
1451{
1452    switch ( mixerId )
1453    {
1454    #if BCHP_CHIP == 7408
1455    case 5:
1456        /* 7408 made this discontiguous for some reason... */
1457        return BCHP_AUD_FMM_DP_CTRL0_MIXER5_CONFIG;
1458    #endif
1459    default:
1460        BDBG_ASSERT(mixerId < BAPE_CHIP_MAX_MIXERS);
1461    #ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG
1462        return BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG + ((BCHP_AUD_FMM_DP_CTRL0_MIXER1_CONFIG-BCHP_AUD_FMM_DP_CTRL0_MIXER0_CONFIG)*mixerId);
1463    #else
1464        return BCHP_AUD_FMM_DP_CTRL0_MIXER_CONFIGi_ARRAY_BASE + ((BCHP_AUD_FMM_DP_CTRL0_MIXER_CONFIGi_ARRAY_ELEMENT_SIZE/8)*mixerId);
1465    #endif
1466    }
1467}
1468
1469static uint32_t BAPE_DpMixer_P_GetInputConfigAddress(
1470    unsigned mixerId,
1471    unsigned inputId
1472    )
1473{
1474    uint32_t regAddr;
1475#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG
1476    regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG + (mixerId*(BCHP_AUD_FMM_DP_CTRL0_MIXER1_INPUT10_CONFIG - BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT10_CONFIG));
1477    regAddr += 4*(inputId/2);
1478#else
1479    switch ( mixerId )
1480    {
1481    case 0:
1482        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT_CONFIGi_ARRAY_BASE; 
1483        break;
1484#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER1_INPUT_CONFIGi_ARRAY_BASE
1485    case 1:
1486        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER1_INPUT_CONFIGi_ARRAY_BASE; 
1487        break;
1488#endif
1489#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER2_INPUT_CONFIGi_ARRAY_BASE
1490    case 2:
1491        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER2_INPUT_CONFIGi_ARRAY_BASE; 
1492        break;
1493#endif
1494#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER3_INPUT_CONFIGi_ARRAY_BASE
1495    case 3:
1496        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER3_INPUT_CONFIGi_ARRAY_BASE; 
1497        break;
1498#endif
1499#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER4_INPUT_CONFIGi_ARRAY_BASE
1500    case 4:
1501        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER4_INPUT_CONFIGi_ARRAY_BASE; 
1502        break;
1503#endif
1504#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER5_INPUT_CONFIGi_ARRAY_BASE
1505    case 5:
1506        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER5_INPUT_CONFIGi_ARRAY_BASE; 
1507        break;
1508#endif
1509#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER6_INPUT_CONFIGi_ARRAY_BASE
1510    case 6:
1511        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER6_INPUT_CONFIGi_ARRAY_BASE; 
1512        break;
1513#endif
1514#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER7_INPUT_CONFIGi_ARRAY_BASE
1515    case 7:
1516        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER7_INPUT_CONFIGi_ARRAY_BASE; 
1517        break;
1518#endif
1519#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER8_INPUT_CONFIGi_ARRAY_BASE
1520    case 8:
1521        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER8_INPUT_CONFIGi_ARRAY_BASE; 
1522        break;
1523#endif
1524#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER9_INPUT_CONFIGi_ARRAY_BASE
1525    case 9:
1526        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER9_INPUT_CONFIGi_ARRAY_BASE; 
1527        break;
1528#endif
1529#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER10_INPUT_CONFIGi_ARRAY_BASE
1530    case 10:
1531        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER10_INPUT_CONFIGi_ARRAY_BASE; 
1532        break;
1533#endif
1534#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER11_INPUT_CONFIGi_ARRAY_BASE
1535    case 11:
1536        regAddr = BCHP_AUD_FMM_DP_CTRL0_MIXER11_INPUT_CONFIGi_ARRAY_BASE; 
1537        break;
1538#endif
1539#ifdef BCHP_AUD_FMM_DP_CTRL0_MIXER12_INPUT_CONFIGi_ARRAY_BASE
1540        #error need to add support for additional mixers
1541#endif
1542    default:
1543        BDBG_ASSERT(mixerId < BAPE_CHIP_MAX_MIXERS);
1544        return 0xffffffff;
1545    }
1546    regAddr += (BCHP_AUD_FMM_DP_CTRL0_MIXER0_INPUT_CONFIGi_ARRAY_ELEMENT_SIZE/8)*inputId;
1547#endif
1548    return regAddr;
1549}
1550
Note: See TracBrowser for help on using the repository browser.