source: svn/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_iop_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: 64.6 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2006-2011, 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_iop_priv.c $
11 * $brcm_Revision: Hydra_Software_Devel/6 $
12 * $brcm_Date: 11/14/11 3:42p $
13 *
14 * Module Description: Audio Decoder Interface
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/ape/7422/bape_iop_priv.c $
19 *
20 * Hydra_Software_Devel/6   11/14/11 3:42p gskerl
21 * SW7429-18: Merging 7429 changes back to main branch.
22 *
23 * Hydra_Software_Devel/SW7429-18/2   11/4/11 5:41p gskerl
24 * SW7429-18: Fixed misspelling BCHP_AUD_FMM_IOP_CTRL_REG_BASE ->
25 * BCHP_AUD_FMM_IOP_CTRL_REG_START. Added missing regAddr arg to
26 * BAPE_Reg_P_UpdateField() call
27 *
28 * Hydra_Software_Devel/SW7429-18/1   10/21/11 6:29p jgarrett
29 * SW7429-18: Initial compileable version for 7429
30 *
31 * Hydra_Software_Devel/5   10/11/11 4:45p jgarrett
32 * SW7425-1349: Setting dummysink outputs to un-grouped by default
33 *
34 * Hydra_Software_Devel/4   9/30/11 11:23a gskerl
35 * SW7231-129: Added support for recovering hardware state after power
36 * standby/resume.
37 *
38 * Hydra_Software_Devel/3   9/16/11 6:52p gskerl
39 * SW7231-129: Refactored to put hardware and software initialization into
40 * separate functions.
41 *
42 * Hydra_Software_Devel/2   4/16/11 12:15p jgarrett
43 * SW7425-371: Removing tab characters
44 *
45 * Hydra_Software_Devel/1   4/6/11 1:24a jgarrett
46 * SW35330-35: Merge to main branch
47 *
48 * Hydra_Software_Devel/SW35330-35/2   4/5/11 7:14p jgarrett
49 * SW35330-35: PCM Playback working on 35230
50 *
51 * Hydra_Software_Devel/SW35330-35/1   4/5/11 12:50p jgarrett
52 * SW35330-35: FMM Abstraction refactoring to support DTV
53 *
54 ***************************************************************************/
55#include "bstd.h"
56#include "bkni.h"
57#include "bape.h"
58#include "bape_priv.h"
59#include "bchp_aud_fmm_bf_ctrl.h"
60
61#ifdef BCHP_AUD_FMM_IOP_LOOPBACK_0_REG_START
62#include "bchp_aud_fmm_iop_loopback_0.h"
63#endif
64
65#ifdef BCHP_AUD_FMM_IOP_DUMMYSINK_0_REG_START
66#include "bchp_aud_fmm_iop_dummysink_0.h"
67#endif
68
69BDBG_MODULE(bape_iop_priv);
70
71typedef struct BAPE_LoopbackGroup
72{
73    bool allocated;
74    bool started;
75    unsigned numChannelPairs;
76    BAPE_Handle deviceHandle;
77    uint32_t loopbackIds[BAPE_ChannelPair_eMax];   
78    BAPE_LoopbackGroupSettings settings;
79} BAPE_LoopbackGroup;
80
81typedef struct BAPE_DummysinkGroup
82{
83    bool allocated;
84    bool started;
85    unsigned numChannelPairs;
86    BAPE_Handle deviceHandle;
87    uint32_t dummysinkIds[BAPE_ChannelPair_eMax];   
88    BAPE_DummysinkGroupSettings settings;
89} BAPE_DummysinkGroup;
90
91#ifdef BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_BASE
92/* Typical STB */
93    #define GET_LOOPBACK_STREAM_ID(idx) ((idx)+BAPE_CHIP_MAX_OUTPUT_PORTS)  /* Loopback output stream ID is always first after the O/P streams */
94    #define GET_DUMMYSINK_STREAM_ID(idx) ((idx)+BAPE_CHIP_MAX_OUTPUT_PORTS+BAPE_CHIP_MAX_LOOPBACKS) /* Dummysink follows loopbacks */
95    #define GET_LOOPBACK_CAPTURE_ID(idx) ((idx))        /* Loopback capture is first on all chips */
96#elif defined BCHP_AUD_FMM_IOP_LOOPBACK_0_REG_START
97    /* 7429-style chips don't use streams */
98#else
99    #error Unknown loopback register layout
100#endif
101
102static BERR_Code BAPE_LoopbackGroup_P_OpenHw( BAPE_LoopbackGroupHandle hLoopbackGroup );
103static void BAPE_Loopback_P_SetGroup(BAPE_Handle deviceHandle, uint32_t loopback, uint32_t group, uint32_t numChannelPairs);
104
105static BERR_Code BAPE_DummysinkGroup_P_OpenHw( BAPE_DummysinkGroupHandle hDummySinkGroup );
106static void BAPE_Dummysink_P_SetGroup(BAPE_Handle deviceHandle, uint32_t dummysink, uint32_t group, uint32_t numChannelPairs);
107
108#ifdef BCHP_AUD_FMM_MS_CTRL_REG_START
109static BERR_Code BAPE_P_InitMsHw(BAPE_Handle handle)
110{
111    unsigned i;
112    uint32_t regVal, regAddr, endAddr;
113    BREG_Handle regHandle;
114
115    BDBG_OBJECT_ASSERT(handle, BAPE_Device);
116
117    regHandle = handle->regHandle;
118
119    /* Initialize the two address blocks to zero */
120    regAddr = BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0;
121    endAddr = BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + (BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_END*(BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_ELEMENT_SIZE/8));
122    while ( regAddr <= endAddr )
123    {
124        BREG_Write32(regHandle, regAddr, 0);
125        regAddr += 4;
126    }
127    regAddr = BCHP_AUD_FMM_MS_CTRL_USEQ_INSTi_ARRAY_BASE;
128    for ( i = 0; i <= BCHP_AUD_FMM_MS_CTRL_USEQ_INSTi_ARRAY_END; i++ )
129    {
130        BREG_Write32(regHandle, regAddr, 0);
131        regAddr += 4;
132    }
133
134    /* Download the firmware */
135    /* Program AUD_FMM_MS_CTRL_USEQ_CTRL: CFG_CTRL to  3 */
136    regVal = BREG_Read32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_CTRL);
137    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_USEQ_CTRL, CFG_CTRL);
138    regVal |= BCHP_FIELD_ENUM(AUD_FMM_MS_CTRL_USEQ_CTRL, CFG_CTRL, Configuration_bits);
139    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_CTRL, regVal);
140
141    /* Program AUD_FMM_MS_CTRL_USEQ_INST+4: INST to 1 */
142    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_INSTi_ARRAY_BASE + 4, 1);
143
144    /* Program AUD_FMM_MS_CTRL_USEQ_CTRL: CFG_CTRL to 2
145             to enable internal access to instruction memory */
146    regVal = BREG_Read32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_CTRL);
147    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_USEQ_CTRL, CFG_CTRL);
148    regVal |= BCHP_FIELD_ENUM(AUD_FMM_MS_CTRL_USEQ_CTRL, CFG_CTRL, Instruction_memory);
149    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_CTRL, regVal);
150
151    /* Copy the microcode to the F/W instruction memory */
152    regAddr = BCHP_AUD_FMM_MS_CTRL_USEQ_INSTi_ARRAY_BASE;
153    for ( i=BCHP_AUD_FMM_MS_CTRL_USEQ_INSTi_ARRAY_START; i <= BCHP_AUD_FMM_MS_CTRL_USEQ_INSTi_ARRAY_END; i++ )
154    {
155        BREG_Write32(regHandle, regAddr, g_BAPE_MS_Firmware[i]);
156        regAddr += 4;
157    }
158
159    /* Now Reset Pico */
160    regVal = BREG_Read32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_CTRL);
161    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_USEQ_CTRL, CFG_CTRL);
162    regVal |= BCHP_FIELD_ENUM(AUD_FMM_MS_CTRL_USEQ_CTRL, CFG_CTRL, Configuration_bits);
163    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_CTRL, regVal);
164
165    /* Program AUD_FMM_MS_CTRL_USEQ_INST+4: INST to 0 */
166    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_INSTi_ARRAY_BASE + 4, 0);
167
168    /* Program AUD_FMM_MS_CTRL_USEQ_CTRL: CFG_CTRL to 0
169             to enable internal access to block external access */
170    regVal = BREG_Read32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_CTRL);
171    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_USEQ_CTRL, CFG_CTRL);
172    regVal |= BCHP_FIELD_ENUM(AUD_FMM_MS_CTRL_USEQ_CTRL, CFG_CTRL, No_external_access);
173    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_CTRL, regVal);
174
175#define BAPE_CBIT_BUFFER_SIZE 12
176    /* Initializing cBits */
177    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE,  0x4);
178    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + 4, 0x200);
179    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + BAPE_CBIT_BUFFER_SIZE *4,   0x4);
180    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + BAPE_CBIT_BUFFER_SIZE * 4 + 4, 0x200);       
181
182    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + 2*BAPE_CBIT_BUFFER_SIZE *4,   0x4);
183    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + 2*BAPE_CBIT_BUFFER_SIZE * 4 + 4,   0x200);       
184    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + 3*BAPE_CBIT_BUFFER_SIZE *4,   0x4);
185    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + 3*BAPE_CBIT_BUFFER_SIZE * 4 + 4,   0x200);       
186
187    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBIT_CTRL_0,   0x50);
188    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_CBIT_CTRL_1,   0x68);
189
190    /*Initializing ramp amount*/
191    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_RAMP_AMOUNT_0,  0x0);           
192    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_RAMP_AMOUNT_1,  0x0);           
193
194    /*Initializing Stream CTRL*/
195    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, 0x112);                   
196    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_1, 0x112);       
197
198    /*Initializing burst*/
199    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_BURST_0, 0x0);       
200    BREG_Write32(regHandle, BCHP_AUD_FMM_MS_CTRL_FW_BURST_1, 0x0);       
201
202    /* Initializing SPDIF cfg */
203    BREG_Write32(regHandle, BCHP_AUD_FMM_OP_CTRL_SPDIF_CFG_0, 0xb);
204
205    return BERR_SUCCESS;
206}
207#endif
208
209static BERR_Code BAPE_P_InitPllSw(BAPE_Handle handle)
210{
211#if BAPE_CHIP_MAX_PLLS
212    int i;
213    BERR_Code errCode = BERR_SUCCESS;
214    BAPE_PllSettings pllSettings;
215
216    BKNI_Memset(&pllSettings, 0, sizeof pllSettings);
217    pllSettings.freeRun = false;
218    pllSettings.vcxo = 0;
219
220    BDBG_OBJECT_ASSERT(handle, BAPE_Device);
221
222    for ( i = 0; i < BAPE_CHIP_MAX_PLLS; i++ )
223    {
224        handle->audioPlls[i].settings = pllSettings;
225    }
226
227    return errCode;
228#else
229    BSTD_UNUSED(handle);
230    return BERR_SUCCESS;
231#endif
232}
233
234
235static BERR_Code BAPE_P_InitPllHw(BAPE_Handle handle)
236{
237#if BAPE_CHIP_MAX_PLLS
238    int i;
239    BERR_Code errCode = BERR_SUCCESS;
240
241
242    BDBG_OBJECT_ASSERT(handle, BAPE_Device);
243
244    for ( i = 0; i < BAPE_CHIP_MAX_PLLS; i++ )
245    {
246        BAPE_PllSettings pllSettings;
247
248        pllSettings =  handle->audioPlls[i].settings;
249
250        errCode = BAPE_Pll_SetSettings(handle, i, &pllSettings);
251        if ( errCode )
252        {
253            return BERR_TRACE(errCode);
254        }
255    }
256
257    return errCode;
258#else
259    BSTD_UNUSED(handle);
260    return BERR_SUCCESS;
261#endif
262}
263
264
265BERR_Code BAPE_P_InitIopSw(BAPE_Handle    handle)
266{
267    BERR_Code errCode;
268    unsigned i;
269
270    /* Initialize PLLs */
271    BDBG_MSG(("Initializing PLLs"));
272    errCode = BAPE_P_InitPllSw(handle);
273    if ( errCode )
274    {
275        return BERR_TRACE(errCode);
276    }
277
278    /* Allocate Loopback Groups */
279    /* Setup Group Handles */
280    BDBG_MSG(("Allocating %u Loopback Groups", BAPE_CHIP_MAX_LOOPBACK_GROUPS));
281    handle->loopbackGroups[0] = BKNI_Malloc(BAPE_CHIP_MAX_LOOPBACK_GROUPS*sizeof(BAPE_LoopbackGroup));
282    if ( NULL == handle->loopbackGroups[0] )
283    {
284        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
285    }
286    BKNI_Memset(handle->loopbackGroups[0], 0, BAPE_CHIP_MAX_LOOPBACK_GROUPS*sizeof(BAPE_LoopbackGroup));
287    for ( i = 1; i < BAPE_CHIP_MAX_LOOPBACK_GROUPS; i++ )
288    {
289        handle->loopbackGroups[i] = handle->loopbackGroups[0] + i;
290    }
291
292    BDBG_MSG(("Allocating %u Dummysink Groups", BAPE_CHIP_MAX_DUMMYSINK_GROUPS));
293    handle->dummysinkGroups[0] = BKNI_Malloc(BAPE_CHIP_MAX_DUMMYSINK_GROUPS*sizeof(BAPE_DummysinkGroup));
294    if ( NULL == handle->dummysinkGroups[0] )
295    {
296        errCode = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
297        goto err_alloc_dummysink;
298    }
299    BKNI_Memset(handle->dummysinkGroups[0], 0, BAPE_CHIP_MAX_DUMMYSINK_GROUPS*sizeof(BAPE_DummysinkGroup));
300    for ( i = 1; i < BAPE_CHIP_MAX_DUMMYSINK_GROUPS; i++ )
301    {
302        handle->dummysinkGroups[i] = handle->dummysinkGroups[0] + i;
303    }
304
305    return BERR_SUCCESS;
306
307err_alloc_dummysink:
308    if ( handle->loopbackGroups[0] )
309    {
310        BKNI_Free(handle->loopbackGroups[0]);
311        BKNI_Memset(handle->loopbackGroups, 0, sizeof(handle->loopbackGroups));
312    }
313    return errCode;
314}
315
316
317BERR_Code BAPE_P_InitIopHw(BAPE_Handle    handle)
318{
319    BERR_Code errCode;
320    unsigned i;
321
322    /* Initialize PLLs */
323    BDBG_MSG(("Initializing PLLs"));
324    errCode = BAPE_P_InitPllHw(handle);
325    if ( errCode )
326    {
327        return BERR_TRACE(errCode);
328    }
329
330#ifdef BCHP_AUD_FMM_MS_CTRL_REG_START
331    /* Initialize Micro Sequencer Registers */
332    BDBG_MSG(("Initializing MS registers"));
333    errCode = BAPE_P_InitMsHw(handle);
334    if ( errCode )
335    {
336        return BERR_TRACE(errCode);
337    }
338#endif
339
340#ifdef BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_BASE
341    BDBG_MSG(("Setting IOP Capture group IDs to default"));
342    {
343        uint32_t regAddr, regVal;
344        regAddr = BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_BASE;
345        for ( i = BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_START; i <= BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_END; i++ )
346        {
347            regVal = BREG_Read32(handle->regHandle, regAddr);
348            regVal &= ~BCHP_MASK(AUD_FMM_IOP_CTRL_CAP_CFGi, GROUP);
349            regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_CAP_CFGi, GROUP, i);
350            BREG_Write32(handle->regHandle, regAddr, regVal);
351            regAddr += BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_ELEMENT_SIZE/8;
352        }
353    }
354#endif
355
356#if BAPE_CHIP_MAX_IOP_STREAMS > 0
357    /* Initialize each stream to defaults */
358    for ( i = 0; i < BAPE_CHIP_MAX_IOP_STREAMS; i++ )
359    {
360        static const BAPE_IopStreamSettings defaultStreamSettings = {24, BAPE_FCI_ID_INVALID};
361        errCode = BAPE_Iop_P_SetStreamSettings(handle, i, &defaultStreamSettings);
362        if ( errCode )
363        {
364            return BERR_TRACE(errCode);
365        }
366    }
367#endif
368
369    /* Initialize each dummysink to default (ungrouped) operation */
370    for ( i = 0; i < BAPE_CHIP_MAX_LOOPBACKS; i++ )
371    {
372        BAPE_Loopback_P_SetGroup(handle, i, i, 1);
373    }
374
375    /* Initialize each dummysink to default (ungrouped) operation */
376    for ( i = 0; i < BAPE_CHIP_MAX_DUMMYSINKS; i++ )
377    {
378        BAPE_Dummysink_P_SetGroup(handle, i, i, 1);
379    }
380
381    return BERR_SUCCESS;
382}
383
384void BAPE_P_UninitIopSw(BAPE_Handle handle)
385{
386    BDBG_OBJECT_ASSERT(handle, BAPE_Device);
387
388    if ( handle->loopbackGroups[0] )
389    {
390        BKNI_Free(handle->loopbackGroups[0]);
391        BKNI_Memset(handle->loopbackGroups, 0, sizeof(handle->loopbackGroups));
392    }
393    if ( handle->dummysinkGroups[0] )
394    {
395        BKNI_Free(handle->dummysinkGroups[0]);
396        BKNI_Memset(handle->dummysinkGroups, 0, sizeof(handle->dummysinkGroups));
397    }
398}
399
400void BAPE_Iop_P_GetStreamSettings(
401    BAPE_Handle handle,
402    unsigned streamId,
403    BAPE_IopStreamSettings *pSettings   /* [out] */
404    )
405{
406#if defined BCHP_AUD_FMM_IOP_CTRL_REG_START
407#ifdef BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_BASE
408    uint32_t regAddr, regVal, value;
409    /* STB chips */
410    BDBG_ASSERT(streamId <= BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_END);  /* END is inclusive */
411    regAddr = BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_BASE + 
412              ((BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_ELEMENT_SIZE/8) * streamId);
413    regVal = BREG_Read32(handle->regHandle, regAddr);
414    value = BCHP_GET_FIELD_DATA(regVal, AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION);
415    switch ( value )
416    {
417    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_16_Bit:
418        pSettings->resolution = 16;
419        break;
420    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_17_Bit:
421        pSettings->resolution = 17;
422        break;
423    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_18_Bit:
424        pSettings->resolution = 18;
425        break;
426    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_19_Bit:
427        pSettings->resolution = 19;
428        break;
429    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_20_Bit:
430        pSettings->resolution = 20;
431        break;
432    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_21_Bit:
433        pSettings->resolution = 21;
434        break;
435    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_22_Bit:
436        pSettings->resolution = 22;
437        break;
438    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_23_Bit:
439        pSettings->resolution = 23;
440        break;
441    default:
442        BDBG_WRN(("Unsupported stream bit resolution field data %u", value));
443        /* Fall through */
444    case BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_STREAM_BIT_RESOLUTION_Res_24_Bit:
445        pSettings->resolution = 24;
446        break;
447    }
448    value = BCHP_GET_FIELD_DATA(regVal, AUD_FMM_IOP_CTRL_FCI_CFGi, ID);
449    pSettings->input = value;
450#elif defined BCHP_AUD_FMM_IOP_CTRL_STRM_RES_16TO19
451    /* DTV chips */
452    uint32_t regAddr, regVal, value, mask, shift;
453    /* Handle Resolution */
454    if ( streamId <= 7 )
455    {
456        regAddr = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7;
457    }
458    else if ( streamId <= 15 )
459    {
460        regAddr = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_8TO15;
461    }
462    else
463    {
464        BDBG_ASSERT(streamId <= 19);
465        regAddr = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_16TO19;
466    }
467    regVal = BREG_Read32(handle->regHandle, regAddr);
468    shift = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM1_BIT_RESOLUTION_SHIFT * (streamId % 8);
469    mask = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_MASK << shift;
470    value = (regVal & mask) >> shift;
471    switch ( value )
472    {
473    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_16:
474        pSettings->resolution = 16;
475        break;
476    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_17:
477        pSettings->resolution = 17;
478        break;
479    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_18:
480        pSettings->resolution = 18;
481        break;
482    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_19:
483        pSettings->resolution = 19;
484        break;
485    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_20:
486        pSettings->resolution = 20;
487        break;
488    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_21:
489        pSettings->resolution = 21;
490        break;
491    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_22:
492        pSettings->resolution = 22;
493        break;
494    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_23:
495        pSettings->resolution = 23;
496        break;
497    default:
498        BDBG_WRN(("Unsupported stream bit resolution field data %u [get] addr %#x id %u shift %u mask %#x", value, regAddr, streamId, shift, mask));
499        /* Fall through */
500    case BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_24:
501        pSettings->resolution = 24;
502        break;
503    }
504    /* Handle ID */
505    BDBG_CASSERT((BCHP_AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP_13_12 - BCHP_AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10) == 36);    /* If these aren't contiguous bad things will happen */
506    regAddr = BCHP_AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10 + (4*(streamId/2));
507    regVal = BREG_Read32(handle->regHandle, regAddr);
508    if ( (streamId % 2) )
509    {
510        /* Odd */
511        value = BCHP_GET_FIELD_DATA(regVal, AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10, STREAM1);
512    }
513    else
514    {
515        /* Even */
516        value = BCHP_GET_FIELD_DATA(regVal, AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10, STREAM0);
517    }
518    pSettings->input = value;
519#else
520#error Unknown IOP Stream Layout
521#endif
522#else
523    BSTD_UNUSED(handle);
524    BSTD_UNUSED(streamId);
525    BSTD_UNUSED(pSettings);
526    BDBG_ERR(("IOP Streams are not supported on this chipset"));
527    BDBG_ASSERT(false);
528#endif
529}
530
531#ifdef BCHP_AUD_FMM_IOP_CTRL_REG_START
532static void BAPE_Iop_P_SetCaptureGroup(
533    BAPE_Handle handle,
534    unsigned captureId,
535    uint32_t value
536    )
537{
538#ifdef BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_BASE
539    uint32_t regAddr, regVal;
540    /* These chips support input grouping (DTV does not) */
541    regAddr = BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_BASE + (4*captureId);
542    regVal = BREG_Read32(handle->regHandle, regAddr);
543    regVal &= ~(BCHP_MASK(AUD_FMM_IOP_CTRL_CAP_CFGi, GROUP));
544    regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_CAP_CFGi, GROUP, value);
545    BREG_Write32(handle->regHandle, regAddr, regVal);
546#else
547    /* No grouping, just carry on */
548    BSTD_UNUSED(handle);
549    BSTD_UNUSED(captureId);
550    BSTD_UNUSED(value);
551#endif
552}
553
554static void BAPE_Iop_P_SetCaptureEnable(
555    BAPE_Handle handle,
556    unsigned captureId,
557    uint32_t value
558    )
559{
560    uint32_t regAddr, regVal;
561#ifdef BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_BASE
562    regAddr = BCHP_AUD_FMM_IOP_CTRL_CAP_CFGi_ARRAY_BASE + (4*captureId);
563    regVal = BREG_Read32(handle->regHandle, regAddr);
564    regVal &= ~(BCHP_MASK(AUD_FMM_IOP_CTRL_CAP_CFGi, ENA));
565    regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_CAP_CFGi, ENA, value);
566    BREG_Write32(handle->regHandle, regAddr, regVal);   
567#elif defined BCHP_AUD_FMM_IOP_CTRL_CAP_CFG
568    regAddr = BCHP_AUD_FMM_IOP_CTRL_CAP_CFG;
569    regVal = BREG_Read32(handle->regHandle, regAddr);
570    regVal &= ~(BCHP_MASK(AUD_FMM_IOP_CTRL_CAP_CFG, ENA0)<<captureId);
571    regVal |= (BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_CAP_CFG, ENA0, value)<<captureId);
572    BREG_Write32(handle->regHandle, regAddr, regVal);   
573#else
574#error Unknown IOP Capture Layout
575#endif
576}
577#endif
578
579BERR_Code BAPE_Iop_P_EnableCapture(
580    BAPE_Handle handle,
581    unsigned baseCaptureId,
582    unsigned numChannelPairs
583    )
584{
585#ifdef BCHP_AUD_FMM_IOP_CTRL_REG_START
586    unsigned i;
587    BDBG_OBJECT_ASSERT(handle, BAPE_Device);
588    /* Set Grouping First */
589    for ( i = 0 ; i < numChannelPairs; i++ )
590    {
591        BAPE_Iop_P_SetCaptureGroup(handle, baseCaptureId+i, baseCaptureId);
592    }
593    /* Start */
594    for ( i = 0 ; i < numChannelPairs; i++ )
595    {
596        BAPE_Iop_P_SetCaptureEnable(handle, baseCaptureId+i, 1);
597    }
598    return BERR_SUCCESS;
599#else
600    BSTD_UNUSED(handle);
601    BSTD_UNUSED(baseCaptureId);
602    BSTD_UNUSED(numChannelPairs);
603    return BERR_TRACE(BERR_NOT_SUPPORTED);
604#endif
605}
606
607void BAPE_Iop_P_DisableCapture(
608    BAPE_Handle handle,
609    unsigned baseCaptureId,
610    unsigned numChannelPairs
611                              )
612{
613#ifdef BCHP_AUD_FMM_IOP_CTRL_REG_START
614    unsigned i;
615    BDBG_OBJECT_ASSERT(handle, BAPE_Device);
616    /* Stop */
617    for ( i = 0 ; i < numChannelPairs; i++ )
618    {
619        BAPE_Iop_P_SetCaptureEnable(handle, baseCaptureId+i, 0);
620    }
621    /* Reset Grouping */
622    for ( i = 0 ; i < numChannelPairs; i++ )
623    {
624        BAPE_Iop_P_SetCaptureGroup(handle, baseCaptureId+i, baseCaptureId+i);
625    }
626#else
627    BSTD_UNUSED(handle);
628    BSTD_UNUSED(baseCaptureId);
629    BSTD_UNUSED(numChannelPairs);
630#endif
631}
632
633BERR_Code BAPE_Iop_P_SetStreamSettings(
634    BAPE_Handle handle,
635    unsigned streamId,
636    const BAPE_IopStreamSettings *pSettings
637    )
638{
639#ifdef BCHP_AUD_FMM_IOP_CTRL_REG_START
640#ifdef BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_BASE
641    uint32_t regAddr, regVal, value;
642    /* STB chips */
643    BDBG_ASSERT(streamId <= BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_END);  /* END is inclusive */
644    regAddr = BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_BASE + 
645              ((BCHP_AUD_FMM_IOP_CTRL_FCI_CFGi_ARRAY_ELEMENT_SIZE/8) * streamId);
646    regVal = BREG_Read32(handle->regHandle, regAddr);
647    regVal &= ~(BCHP_MASK(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION)|
648                BCHP_MASK(AUD_FMM_IOP_CTRL_FCI_CFGi, ID));
649    switch ( pSettings->resolution )
650    {
651    case 16:
652        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_16_Bit);
653        break;
654    case 17:
655        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_17_Bit);
656        break;
657    case 18:
658        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_18_Bit);
659        break;
660    case 19:
661        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_19_Bit);
662        break;
663    case 20:
664        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_20_Bit);
665        break;
666    case 21:
667        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_21_Bit);
668        break;
669    case 22:
670        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_22_Bit);
671        break;
672    case 23:
673        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_23_Bit);
674        break;
675    case 24:
676        value = BCHP_FIELD_ENUM(AUD_FMM_IOP_CTRL_FCI_CFGi, STREAM_BIT_RESOLUTION, Res_24_Bit);
677        break;
678    default:
679        BDBG_ERR(("Unsupported stream bit resolution field data %u", pSettings->resolution));
680        return BERR_TRACE(BERR_INVALID_PARAMETER);
681    }
682    regVal |= value;
683    regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_FCI_CFGi, ID, pSettings->input);
684    BREG_Write32(handle->regHandle, regAddr, regVal);
685#elif defined BCHP_AUD_FMM_IOP_CTRL_STRM_RES_16TO19
686    /* DTV chips */
687    uint32_t regAddr, regVal, value, mask, shift;
688    /* Handle Resolution */
689    if ( streamId <= 7 )
690    {
691        regAddr = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7;
692    }
693    else if ( streamId <= 15 )
694    {
695        regAddr = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_8TO15;
696    }
697    else
698    {
699        BDBG_ASSERT(streamId <= 19);
700        regAddr = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_16TO19;
701    }
702    regVal = BREG_Read32(handle->regHandle, regAddr);
703    shift = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM1_BIT_RESOLUTION_SHIFT * (streamId % 8);
704    mask = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_MASK << shift;
705    regVal &= ~mask;
706    switch ( pSettings->resolution )
707    {
708    case 16:
709        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_16;
710        break;
711    case 17:
712        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_17;
713        break;
714    case 18:
715        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_18;
716        break;
717    case 19:
718        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_19;
719        break;
720    case 20:
721        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_20;
722        break;
723    case 21:
724        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_21;
725        break;
726    case 22:
727        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_22;
728        break;
729    case 23:
730        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_23;
731        break;
732    case 24:
733        value = BCHP_AUD_FMM_IOP_CTRL_STRM_RES_0TO7_STREAM0_BIT_RESOLUTION_RES_24;
734        break;
735    default:
736        BDBG_ERR(("Unsupported stream bit resolution field data %u [set]", pSettings->resolution));
737        return BERR_TRACE(BERR_INVALID_PARAMETER);
738    }
739    regVal |= value << shift;
740    BREG_Write32(handle->regHandle, regAddr, regVal);
741    /* Handle ID */
742    BDBG_CASSERT((BCHP_AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP_13_12 - BCHP_AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10) == 36);    /* If these aren't contiguous bad things will happen */
743    regAddr = BCHP_AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10 + (4*(streamId/2));
744    regVal = BREG_Read32(handle->regHandle, regAddr);
745    if ( (streamId % 2) )
746    {
747        /* Odd */
748        regVal &= ~BCHP_MASK(AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10, STREAM1);
749        regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10, STREAM1, pSettings->input);
750    }
751    else
752    {
753        /* Even */
754        regVal &= ~BCHP_MASK(AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10, STREAM0);
755        regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_MIX_IOP_IDMAP10, STREAM0, pSettings->input);
756    }
757    BREG_Write32(handle->regHandle, regAddr, regVal);
758#else
759#error Unknown IOP Stream Layout
760#endif
761    return BERR_SUCCESS;
762#else
763    BSTD_UNUSED(handle);
764    BSTD_UNUSED(streamId);
765    BSTD_UNUSED(pSettings);
766    return BERR_TRACE(BERR_NOT_SUPPORTED);
767#endif
768}
769
770void BAPE_LoopbackGroup_P_GetDefaultCreateSettings(BAPE_LoopbackGroupCreateSettings *pSettings  /* [out] */ )
771{
772    BDBG_ASSERT(NULL != pSettings);
773    pSettings->numChannelPairs = 1;
774}
775
776BERR_Code BAPE_LoopbackGroup_P_Create(
777    BAPE_Handle deviceHandle,
778    const BAPE_LoopbackGroupCreateSettings *pSettings,
779    BAPE_LoopbackGroupHandle *pHandle       /* [out] */
780    )
781{
782    unsigned i, loopback;
783    BERR_Code errCode;
784    BAPE_LoopbackGroupHandle handle=NULL;
785
786    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
787    BDBG_ASSERT(NULL != pSettings);
788    BDBG_ASSERT(NULL != pHandle);
789    BDBG_ASSERT(pSettings->numChannelPairs <= BAPE_ChannelPair_eMax);
790
791    /* Find an available group handle */
792    for ( i = 0; i < BAPE_CHIP_MAX_LOOPBACK_GROUPS; i++ )
793    {
794        BDBG_ASSERT(NULL != deviceHandle->loopbackGroups[i]);
795        if ( !deviceHandle->loopbackGroups[i]->allocated )
796        {
797            handle = deviceHandle->loopbackGroups[i];
798            break;
799        }
800    }
801
802    /* If none found, return error */
803    if ( NULL == handle )
804    {
805        return BERR_TRACE(BERR_NOT_SUPPORTED);
806    }
807
808    /* Now search for the correct number of resources */
809    errCode = BAPE_P_AllocateFmmResource(deviceHandle, BAPE_FmmResourceType_eLoopback, pSettings->numChannelPairs, &loopback);
810    if ( errCode )
811    {
812        errCode = BERR_TRACE(errCode);
813        goto err_alloc_loopback;
814    }
815
816    /* Successfully allocated resources.  Initialize Group */
817    BKNI_Memset(handle, 0, sizeof(BAPE_LoopbackGroup));
818    handle->allocated = true;
819    handle->started = false;
820    handle->numChannelPairs = pSettings->numChannelPairs;
821    handle->deviceHandle = deviceHandle;
822    for ( i = 0; i < pSettings->numChannelPairs; i++ )
823    {
824        handle->loopbackIds[i] = loopback + i;
825        /* Loopbacks don't support grouping on any chips today */
826    }
827    BAPE_FciIdGroup_Init(&handle->settings.input);
828#if BAPE_CHIP_MAX_FS > 0
829    handle->settings.fs = 0;
830#else
831    handle->settings.mclkSource = BAPE_MclkSource_ePll0;
832    handle->settings.pllChannel = 0;
833    handle->settings.mclkFreqToFsRatio = BAPE_BASE_PLL_TO_FS_RATIO;
834#endif
835    handle->settings.resolution = 24;
836
837    /* Initialize the hardware for this group */
838    errCode = BAPE_LoopbackGroup_P_OpenHw(handle);
839    if ( errCode )
840    {
841        (void)BERR_TRACE(errCode);
842        goto err_after_alloc_loopback;
843    }
844
845    /* Make sure FS is set */
846    (void)BAPE_LoopbackGroup_P_SetSettings(handle, &handle->settings);
847    *pHandle = handle;
848    return BERR_SUCCESS;
849
850err_after_alloc_loopback:
851    BAPE_LoopbackGroup_P_Destroy(handle);
852    /* fall through */
853err_alloc_loopback:
854    return errCode; 
855}
856
857void BAPE_LoopbackGroup_P_Destroy(BAPE_LoopbackGroupHandle handle)
858{
859    unsigned i;
860
861    BDBG_ASSERT(NULL != handle);
862    BDBG_ASSERT(handle->allocated);
863    BDBG_ASSERT(!handle->started);
864    BDBG_OBJECT_ASSERT(handle->deviceHandle, BAPE_Device);
865
866    for ( i = 0; i < handle->numChannelPairs; i++ )
867    {
868        /* Revert to ungrouped */
869        BAPE_Loopback_P_SetGroup(handle->deviceHandle, handle->loopbackIds[i], handle->loopbackIds[i], handle->numChannelPairs);
870    }
871    /* Release Resources */
872    BAPE_P_FreeFmmResource(handle->deviceHandle, BAPE_FmmResourceType_eLoopback, handle->numChannelPairs, handle->loopbackIds[0]);
873    BKNI_Memset(handle->loopbackIds, 0xff, sizeof(handle->loopbackIds));
874    handle->allocated = false;
875}
876
877void BAPE_LoopbackGroup_P_GetSettings(
878    BAPE_LoopbackGroupHandle handle,
879    BAPE_LoopbackGroupSettings *pSettings   /* [out] */
880    )
881{
882    BDBG_ASSERT(NULL != handle);
883    BDBG_ASSERT(handle->allocated);
884    *pSettings = handle->settings;
885}
886
887BERR_Code BAPE_LoopbackGroup_P_SetSettings(
888    BAPE_LoopbackGroupHandle handle,
889    const BAPE_LoopbackGroupSettings *pSettings
890    )
891{
892    uint32_t regAddr, regVal;
893    unsigned i;
894
895    BDBG_ASSERT(NULL != handle);
896    BDBG_ASSERT(handle->allocated);
897    handle->settings = *pSettings;
898
899#ifdef BCHP_AUD_FMM_IOP_CTRL_LOOPBACK_CFGi_ARRAY_BASE
900    for ( i = 0; i < handle->numChannelPairs; i++ )
901    {
902        /* Typical STB */
903        regAddr = BCHP_AUD_FMM_IOP_CTRL_LOOPBACK_CFGi_ARRAY_BASE + (4*handle->loopbackIds[i]);
904        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
905        regVal &= ~BCHP_MASK(AUD_FMM_IOP_CTRL_LOOPBACK_CFGi, TMG_SRC_SEL);
906        regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_LOOPBACK_CFGi, TMG_SRC_SEL, pSettings->fs);
907        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
908    }
909#elif defined BCHP_AUD_FMM_IOP_CTRL_LOOPBACK_CFG
910    /* Typical DTV */
911    regAddr = BCHP_AUD_FMM_IOP_CTRL_LOOPBACK_CFG;
912    regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
913    for ( i = 0; i < handle->numChannelPairs; i++ )
914    {
915        uint32_t mask, value;
916        switch ( handle->loopbackIds[i] )
917        {
918        default: 
919            BDBG_ASSERT(0); /* Should never be possible */
920            /* Fall through */
921        case 0:
922            mask = BCHP_MASK(AUD_FMM_IOP_CTRL_LOOPBACK_CFG, TMG_SRC_SEL0); 
923            value = BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_LOOPBACK_CFG, TMG_SRC_SEL0, pSettings->fs); 
924            break;
925        case 1:
926            mask = BCHP_MASK(AUD_FMM_IOP_CTRL_LOOPBACK_CFG, TMG_SRC_SEL1); 
927            value = BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_LOOPBACK_CFG, TMG_SRC_SEL1, pSettings->fs); 
928            break;
929        case 2:
930            mask = BCHP_MASK(AUD_FMM_IOP_CTRL_LOOPBACK_CFG, TMG_SRC_SEL2); 
931            value = BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_LOOPBACK_CFG, TMG_SRC_SEL2, pSettings->fs); 
932            break;
933        case 3:
934            mask = BCHP_MASK(AUD_FMM_IOP_CTRL_LOOPBACK_CFG, TMG_SRC_SEL3); 
935            value = BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_LOOPBACK_CFG, TMG_SRC_SEL3, pSettings->fs); 
936            break;
937        }
938        regVal = (regVal & (~mask))|value;
939    }
940    BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
941#elif defined BCHP_AUD_FMM_IOP_LOOPBACK_0_REG_START
942    /* 7429-style */
943    BSTD_UNUSED(regVal);
944    for ( i = 0; i < handle->numChannelPairs; i++ )
945    {
946        BAPE_Reg_P_FieldList regFieldList;
947
948        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, handle->loopbackIds[i]);
949        BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
950        switch ( handle->settings.mclkSource ) 
951        {
952#ifdef BCHP_AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i_PLLCLKSEL_PLL0_ch1
953        case BAPE_MclkSource_ePll0:
954            switch ( handle->settings.pllChannel )
955            {
956            case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL0_ch1); break;
957            case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL0_ch2); break;
958            case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL0_ch3); break;               
959            default: return BERR_TRACE(BERR_NOT_SUPPORTED);
960            }
961            break;
962#endif
963#ifdef BCHP_AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i_PLLCLKSEL_PLL1_ch1
964        case BAPE_MclkSource_ePll1:
965            switch ( handle->settings.pllChannel )
966            {
967            case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL1_ch1); break;
968            case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL1_ch2); break;
969            case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL1_ch3); break;               
970            default: return BERR_TRACE(BERR_NOT_SUPPORTED);
971            }
972            break;
973#endif
974#ifdef BCHP_AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i_PLLCLKSEL_PLL2_ch1
975        case BAPE_MclkSource_ePll2:
976            switch ( handle->settings.pllChannel )
977            {
978            case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL2_ch1); break;
979            case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL2_ch2); break;
980            case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, PLL2_ch3); break;               
981            default: return BERR_TRACE(BERR_NOT_SUPPORTED);
982            }
983            break;
984#endif
985#ifdef BCHP_AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i_PLLCLKSEL_Mclk_gen0
986        case BAPE_MclkSource_eNco0:
987            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, Mclk_gen0); 
988            break;
989#endif
990#ifdef BCHP_AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i_PLLCLKSEL_Mclk_gen1
991        case BAPE_MclkSource_eNco1:
992            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, Mclk_gen1); 
993            break;
994#endif
995#ifdef BCHP_AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i_PLLCLKSEL_Mclk_gen2
996        case BAPE_MclkSource_eNco2:
997            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, PLLCLKSEL, Mclk_gen2); 
998            break;
999#endif
1000        default:
1001            BDBG_ERR(("Unsupported clock source %u for Loopback %u", handle->settings.mclkSource, handle->loopbackIds[i]));
1002            return BERR_TRACE(BERR_NOT_SUPPORTED);
1003        }
1004        switch ( handle->settings.mclkFreqToFsRatio )
1005        {
1006        case 128: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, MCLK_RATE, MCLK_128fs_SCLK_64fs); break;
1007        case 256: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, MCLK_RATE, MCLK_256fs_SCLK_64fs); break;
1008        case 384: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, MCLK_RATE, MCLK_384fs_SCLK_64fs); break;
1009        case 512: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_MCLK_CFG_i, MCLK_RATE, MCLK_512fs_SCLK_64fs); break;
1010        default:
1011            BDBG_ERR(("Unsupported MCLK Rate of %uFs", handle->settings.mclkFreqToFsRatio));
1012            return BERR_TRACE(BERR_NOT_SUPPORTED);
1013        }
1014        BAPE_Reg_P_ApplyFieldList(&regFieldList, regAddr);
1015    }
1016#else
1017#error Unknown loopback register layout
1018#endif
1019
1020    return BERR_SUCCESS;
1021}
1022
1023BERR_Code BAPE_LoopbackGroup_P_Start(BAPE_LoopbackGroupHandle handle)
1024{
1025    BERR_Code errCode;
1026    unsigned i;
1027
1028    BDBG_ASSERT(NULL != handle);
1029    BDBG_ASSERT(handle->allocated);
1030    BDBG_ASSERT(!handle->started);
1031
1032#ifdef BCHP_AUD_FMM_IOP_CTRL_REG_START
1033    /* Set input FCI */
1034    for ( i = 0; i < handle->numChannelPairs; i++ )
1035    {
1036        BAPE_IopStreamSettings streamSettings;
1037        unsigned streamId;
1038        streamId = GET_LOOPBACK_STREAM_ID(handle->loopbackIds[i]);
1039        BAPE_Iop_P_GetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1040        streamSettings.resolution = handle->settings.resolution;
1041        streamSettings.input = handle->settings.input.ids[i];
1042        errCode = BAPE_Iop_P_SetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1043        if ( errCode )
1044        {
1045            return BERR_TRACE(errCode);
1046        }
1047    }
1048
1049    /* Enable Capture */
1050    BDBG_MSG(("Enabling loopback capture"));
1051    errCode = BAPE_Iop_P_EnableCapture(handle->deviceHandle, GET_LOOPBACK_CAPTURE_ID(handle->loopbackIds[0]), handle->numChannelPairs);
1052    if ( errCode )
1053    {
1054        return BERR_TRACE(errCode);
1055    }
1056#else
1057    BSTD_UNUSED(errCode);
1058    /* Newer 7429-style chips */
1059    for ( i = 0; i < handle->numChannelPairs; i++ )
1060    {
1061        uint32_t regAddr;
1062        BAPE_Reg_P_FieldList regFieldList;
1063
1064        /* Configure Loopback "output" interface */
1065        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, handle->loopbackIds[i]);
1066        BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
1067        switch ( handle->settings.resolution )
1068        {
1069        case 16: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_16_Bit); break;
1070        case 17: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_17_Bit); break;
1071        case 18: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_18_Bit); break;
1072        case 19: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_19_Bit); break;
1073        case 20: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_20_Bit); break;
1074        case 21: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_21_Bit); break;
1075        case 22: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_22_Bit); break;
1076        case 23: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_23_Bit); break;
1077        case 24: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, STREAM_BIT_RESOLUTION, Res_24_Bit); break;
1078        default: 
1079            BDBG_ERR(("Invalid loopback stream resolution (%u)", handle->settings.resolution)); 
1080            return BERR_TRACE(BERR_NOT_SUPPORTED);
1081        }
1082        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, FCI_ID, handle->settings.input.ids[i]);
1083        BAPE_Reg_P_ApplyFieldList(&regFieldList, regAddr);
1084
1085        /* Configure loopback "capture" interface */
1086        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, handle->loopbackIds[i]);
1087        BAPE_Reg_P_UpdateField(handle->deviceHandle, regAddr, AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, CAP_GROUP_ID, handle->loopbackIds[0]);
1088    }
1089
1090    /* Now that both input and output are configured, enable the interface.  Enable capture first and then the output (consumer..producer) */
1091    for ( i = 0; i < handle->numChannelPairs; i++ )
1092    {
1093        uint32_t regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, handle->loopbackIds[i]);
1094        BAPE_Reg_P_UpdateField(handle->deviceHandle, regAddr, AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, CAP_ENA, 1);
1095    }
1096
1097    for ( i = 0; i < handle->numChannelPairs; i++ )
1098    {
1099        uint32_t regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, handle->loopbackIds[i]);
1100        BAPE_Reg_P_UpdateField(handle->deviceHandle, regAddr, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, ENA, 1);
1101    }
1102#endif
1103
1104    handle->started = true;
1105
1106    return BERR_SUCCESS;
1107}
1108
1109void BAPE_LoopbackGroup_P_Stop(BAPE_LoopbackGroupHandle handle)
1110{
1111    unsigned i;
1112    BDBG_ASSERT(NULL != handle);
1113    BDBG_ASSERT(handle->allocated);
1114
1115    if ( !handle->started )
1116    {
1117        return;
1118    }
1119
1120#ifdef BCHP_AUD_FMM_IOP_CTRL_REG_START
1121    /* Disable Capture */
1122    BDBG_MSG(("Disabling loopback capture"));
1123    BAPE_Iop_P_DisableCapture(handle->deviceHandle, GET_LOOPBACK_CAPTURE_ID(handle->loopbackIds[0]), handle->numChannelPairs);
1124
1125    /* Set input FCI to invalid */
1126    for ( i = 0; i < handle->numChannelPairs; i++ )
1127    {
1128        BAPE_IopStreamSettings streamSettings;
1129        unsigned streamId;
1130        BERR_Code errCode;
1131        streamId = GET_LOOPBACK_STREAM_ID(handle->loopbackIds[i]);
1132        BAPE_Iop_P_GetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1133        streamSettings.input = BAPE_FCI_ID_INVALID;
1134        errCode = BAPE_Iop_P_SetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1135        if ( errCode )
1136        {
1137            (void)BERR_TRACE(errCode);
1138        }
1139    }
1140#else
1141    /* Disable the interface */
1142    for ( i = 0; i < handle->numChannelPairs; i++ )
1143    {
1144        uint32_t regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, handle->loopbackIds[i]);
1145        BAPE_Reg_P_UpdateField(handle->deviceHandle, regAddr, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, ENA, 0);
1146    }
1147
1148    for ( i = 0; i < handle->numChannelPairs; i++ )
1149    {
1150        uint32_t regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, handle->loopbackIds[i]);
1151        BAPE_Reg_P_UpdateField(handle->deviceHandle, regAddr, AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, CAP_ENA, 0);
1152    }
1153
1154    /* Clear any grouping */
1155    for ( i = 0; i < handle->numChannelPairs; i++ )
1156    {
1157        uint32_t regAddr;
1158        BAPE_Reg_P_FieldList regFieldList;
1159
1160        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, handle->loopbackIds[i]);
1161        BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
1162        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, GROUP_ID, handle->loopbackIds[i]);
1163        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, CHANNEL_GROUPING, 1);
1164        BAPE_Reg_P_ApplyFieldList(&regFieldList, regAddr);
1165
1166        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, handle->loopbackIds[i]);
1167        BAPE_Reg_P_UpdateField(handle->deviceHandle, regAddr, AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, CAP_GROUP_ID, handle->loopbackIds[i]);
1168    }
1169
1170#endif
1171
1172    handle->started = false;
1173}
1174
1175void BAPE_LoopbackGroup_P_GetCaptureFciIds(
1176    BAPE_LoopbackGroupHandle handle,
1177    BAPE_FciIdGroup *pGroup             /* [out] */
1178    )
1179{
1180    unsigned i;
1181    BDBG_ASSERT(NULL != handle);
1182    BDBG_ASSERT(handle->allocated);
1183    BDBG_ASSERT(NULL != pGroup);
1184
1185    BAPE_FciIdGroup_Init(pGroup);
1186
1187#ifdef BCHP_AUD_FMM_IOP_CTRL_REG_START
1188    /* Thankfully on all chips so far, loopback is the first set of captures */
1189    for ( i = 0; i < handle->numChannelPairs; i++ )
1190    {
1191        pGroup->ids[i] = (0x6<<6)|GET_LOOPBACK_CAPTURE_ID(handle->loopbackIds[i]);
1192    }
1193#else
1194    {
1195        uint32_t startId;
1196
1197        startId = BCHP_GET_FIELD_DATA(
1198            BAPE_Reg_P_Read(handle->deviceHandle, BCHP_AUD_FMM_IOP_LOOPBACK_0_CAPTURE_FCI_ID_TABLE),
1199            AUD_FMM_IOP_LOOPBACK_0_CAPTURE_FCI_ID_TABLE, 
1200            START_FCI_ID);
1201
1202        for ( i = 0; i < handle->numChannelPairs; i++ )
1203        {
1204            pGroup->ids[i] = handle->loopbackIds[i] + startId;
1205        }
1206    }
1207#endif
1208}
1209
1210BERR_Code BAPE_LoopbackGroup_P_ResumeFromStandby(BAPE_Handle bapeHandle)
1211{
1212    BERR_Code   errCode = BERR_SUCCESS;
1213    unsigned    i;
1214
1215    BDBG_OBJECT_ASSERT(bapeHandle, BAPE_Device);
1216
1217    /* For each opened LoopbackGroup, call the functions necessary to restore the hardware to it's appropriate state. */
1218    for ( i=0 ; i<BAPE_CHIP_MAX_LOOPBACK_GROUPS ; i++ )
1219    {
1220        if ( bapeHandle->loopbackGroups[i]->allocated )       /* If this one is open... */
1221        {
1222            BAPE_LoopbackGroupHandle hLoopbackGroup = bapeHandle->loopbackGroups[i];
1223
1224            /* Put the HW into the generic open state. */
1225            errCode = BAPE_LoopbackGroup_P_OpenHw(hLoopbackGroup );
1226            if ( errCode ) return BERR_TRACE(errCode);
1227           
1228            /* Now apply changes for the settings struct. */
1229            errCode = BAPE_LoopbackGroup_P_SetSettings(hLoopbackGroup, &hLoopbackGroup->settings);
1230            if ( errCode ) return BERR_TRACE(errCode);
1231
1232            /* Now restore the dynamic stuff from the values saved in the device struct. */
1233                /* Nothing to do for this. */
1234        }
1235    }
1236    return errCode;
1237}
1238
1239static BERR_Code BAPE_LoopbackGroup_P_OpenHw( BAPE_LoopbackGroupHandle hLoopbackGroup )
1240{
1241    unsigned i;
1242
1243    BDBG_ASSERT(NULL != hLoopbackGroup);
1244    BDBG_ASSERT(hLoopbackGroup->allocated);
1245
1246    for ( i = 0; i < hLoopbackGroup->numChannelPairs; i++ )
1247    {
1248        BAPE_Loopback_P_SetGroup(hLoopbackGroup->deviceHandle, hLoopbackGroup->loopbackIds[i], hLoopbackGroup->loopbackIds[0], hLoopbackGroup->numChannelPairs);
1249    }
1250
1251    return BERR_SUCCESS;
1252}
1253
1254void BAPE_DummysinkGroup_P_GetDefaultCreateSettings(BAPE_DummysinkGroupCreateSettings *pSettings  /* [out] */ )
1255{
1256    BDBG_ASSERT(NULL != pSettings);
1257    pSettings->numChannelPairs = 1;
1258}
1259
1260BERR_Code BAPE_DummysinkGroup_P_Create(
1261    BAPE_Handle deviceHandle,
1262    const BAPE_DummysinkGroupCreateSettings *pSettings,
1263    BAPE_DummysinkGroupHandle *pHandle      /* [out] */
1264    )
1265{
1266    unsigned i, dummysink;
1267    BERR_Code errCode;
1268    BAPE_DummysinkGroupHandle handle=NULL;
1269
1270    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1271    BDBG_ASSERT(NULL != pSettings);
1272    BDBG_ASSERT(NULL != pHandle);
1273    BDBG_ASSERT(pSettings->numChannelPairs <= BAPE_ChannelPair_eMax);
1274
1275    /* Find an available group handle */
1276    for ( i = 0; i < BAPE_CHIP_MAX_DUMMYSINK_GROUPS; i++ )
1277    {
1278        BDBG_ASSERT(NULL != deviceHandle->dummysinkGroups[i]);
1279        if ( !deviceHandle->dummysinkGroups[i]->allocated )
1280        {
1281            handle = deviceHandle->dummysinkGroups[i];
1282            break;
1283        }
1284    }
1285
1286    /* If none found, return error */
1287    if ( NULL == handle )
1288    {
1289        return BERR_TRACE(BERR_NOT_SUPPORTED);
1290    }
1291
1292    /* Now search for the correct number of resources */
1293    errCode = BAPE_P_AllocateFmmResource(deviceHandle, BAPE_FmmResourceType_eDummysink, pSettings->numChannelPairs, &dummysink);
1294    if ( errCode )
1295    {
1296        errCode = BERR_TRACE(errCode);
1297        goto err_alloc_dummysink;
1298    }
1299
1300    /* Successfully allocated resources.  Initialize Group */
1301    BKNI_Memset(handle, 0, sizeof(BAPE_DummysinkGroup));
1302    handle->allocated = true;
1303    handle->started = false;
1304    handle->numChannelPairs = pSettings->numChannelPairs;
1305    handle->deviceHandle = deviceHandle;
1306    BAPE_FciIdGroup_Init(&handle->settings.input);
1307    handle->settings.resolution = 24;
1308#if BAPE_CHIP_MAX_FS > 0
1309    handle->settings.fs = 0;
1310#else
1311    handle->settings.mclkSource = BAPE_MclkSource_ePll0;
1312    handle->settings.pllChannel = 0;
1313    handle->settings.mclkFreqToFsRatio = BAPE_BASE_PLL_TO_FS_RATIO;
1314#endif
1315
1316    for ( i = 0; i < handle->numChannelPairs; i++ )
1317    {
1318        handle->dummysinkIds[i] = dummysink + i;
1319    }
1320
1321    /* Initialize the hardware for this group */
1322    errCode = BAPE_DummysinkGroup_P_OpenHw(handle);
1323    if ( errCode )
1324    {
1325        (void)BERR_TRACE(errCode);
1326        goto err_after_alloc_dummysink;
1327    }
1328
1329    /* Make sure FS is set */
1330    (void)BAPE_DummysinkGroup_P_SetSettings(handle, &handle->settings);
1331    *pHandle = handle;
1332    return BERR_SUCCESS;
1333
1334err_after_alloc_dummysink:
1335    handle->allocated = false;
1336    /* fall through */
1337err_alloc_dummysink:
1338    return errCode; 
1339}
1340
1341void BAPE_DummysinkGroup_P_Destroy(BAPE_DummysinkGroupHandle handle)
1342{
1343    unsigned i;
1344    BDBG_ASSERT(NULL != handle);
1345    BDBG_ASSERT(handle->allocated);
1346    BDBG_ASSERT(!handle->started);
1347    BDBG_OBJECT_ASSERT(handle->deviceHandle, BAPE_Device);
1348    /* Release Resources */
1349    for ( i = 0; i < handle->numChannelPairs; i++ )
1350    {
1351        /* Revert to ungrouped */
1352        BAPE_Dummysink_P_SetGroup(handle->deviceHandle, handle->dummysinkIds[i], handle->dummysinkIds[i], handle->numChannelPairs);
1353    }
1354    BAPE_P_FreeFmmResource(handle->deviceHandle, BAPE_FmmResourceType_eDummysink, handle->numChannelPairs, handle->dummysinkIds[0]);
1355    BKNI_Memset(handle->dummysinkIds, 0xff, sizeof(handle->dummysinkIds));
1356    handle->allocated = false;
1357}
1358
1359void BAPE_DummysinkGroup_P_GetSettings(
1360    BAPE_DummysinkGroupHandle handle,
1361    BAPE_DummysinkGroupSettings *pSettings  /* [out] */
1362    )
1363{
1364    BDBG_ASSERT(NULL != handle);
1365    BDBG_ASSERT(handle->allocated);
1366    *pSettings = handle->settings;
1367}
1368
1369BERR_Code BAPE_DummysinkGroup_P_SetSettings(
1370    BAPE_DummysinkGroupHandle handle,
1371    const BAPE_DummysinkGroupSettings *pSettings
1372    )
1373{
1374    uint32_t regAddr, regVal;
1375    unsigned i;
1376
1377    BDBG_ASSERT(NULL != handle);
1378    BDBG_ASSERT(handle->allocated);
1379    handle->settings = *pSettings;
1380
1381#ifdef BCHP_AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi_ARRAY_BASE
1382    /* Set FS timing source */
1383    for ( i = 0; i < handle->numChannelPairs; i++ )
1384    {
1385        regAddr = BCHP_AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi_ARRAY_BASE + (4*handle->dummysinkIds[i]);
1386        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1387        regVal &= ~BCHP_MASK(AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi, TMG_SRC_SEL);
1388        regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi, TMG_SRC_SEL, pSettings->fs);
1389        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1390    }
1391#else
1392    /* 7429-style */
1393    BSTD_UNUSED(regVal);
1394    for ( i = 0; i < handle->numChannelPairs; i++ )
1395    {
1396        BAPE_Reg_P_FieldList regFieldList;
1397
1398        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, handle->dummysinkIds[i]);
1399        BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
1400        switch ( handle->settings.mclkSource ) 
1401        {
1402#ifdef BCHP_AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i_PLLCLKSEL_PLL0_ch1
1403        case BAPE_MclkSource_ePll0:
1404            switch ( handle->settings.pllChannel )
1405            {
1406            case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL0_ch1); break;
1407            case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL0_ch2); break;
1408            case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL0_ch3); break;               
1409            default: return BERR_TRACE(BERR_NOT_SUPPORTED);
1410            }
1411            break;
1412#endif
1413#ifdef BCHP_AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i_PLLCLKSEL_PLL1_ch1
1414        case BAPE_MclkSource_ePll1:
1415            switch ( handle->settings.pllChannel )
1416            {
1417            case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL1_ch1); break;
1418            case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL1_ch2); break;
1419            case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL1_ch3); break;               
1420            default: return BERR_TRACE(BERR_NOT_SUPPORTED);
1421            }
1422            break;
1423#endif
1424#ifdef BCHP_AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i_PLLCLKSEL_PLL2_ch1
1425        case BAPE_MclkSource_ePll2:
1426            switch ( handle->settings.pllChannel )
1427            {
1428            case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL2_ch1); break;
1429            case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL2_ch2); break;
1430            case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, PLL2_ch3); break;               
1431            default: return BERR_TRACE(BERR_NOT_SUPPORTED);
1432            }
1433            break;
1434#endif
1435#ifdef BCHP_AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i_PLLCLKSEL_Mclk_gen0
1436        case BAPE_MclkSource_eNco0:
1437            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, Mclk_gen0); 
1438            break;
1439#endif
1440#ifdef BCHP_AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i_PLLCLKSEL_Mclk_gen1
1441        case BAPE_MclkSource_eNco1:
1442            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, Mclk_gen1); 
1443            break;
1444#endif
1445#ifdef BCHP_AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i_PLLCLKSEL_Mclk_gen2
1446        case BAPE_MclkSource_eNco2:
1447            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, PLLCLKSEL, Mclk_gen2); 
1448            break;
1449#endif
1450        default:
1451            BDBG_ERR(("Unsupported clock source %u for Loopback %u", handle->settings.mclkSource, handle->dummysinkIds[i]));
1452            return BERR_TRACE(BERR_NOT_SUPPORTED);
1453        }
1454        switch ( handle->settings.mclkFreqToFsRatio )
1455        {
1456        case 128: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, MCLK_RATE, MCLK_128fs_SCLK_64fs); break;
1457        case 256: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, MCLK_RATE, MCLK_256fs_SCLK_64fs); break;
1458        case 384: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, MCLK_RATE, MCLK_384fs_SCLK_64fs); break;
1459        case 512: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_MCLK_CFG_i, MCLK_RATE, MCLK_512fs_SCLK_64fs); break;
1460        default:
1461            BDBG_ERR(("Unsupported MCLK Rate of %uFs", handle->settings.mclkFreqToFsRatio));
1462            return BERR_TRACE(BERR_NOT_SUPPORTED);
1463        }
1464        BAPE_Reg_P_ApplyFieldList(&regFieldList, regAddr);
1465    }   
1466#endif
1467
1468    return BERR_SUCCESS;
1469}
1470
1471BERR_Code BAPE_DummysinkGroup_P_Start(BAPE_DummysinkGroupHandle handle)
1472{
1473    BERR_Code errCode;
1474    uint32_t regAddr, regVal;
1475    unsigned i;
1476
1477    BDBG_ASSERT(NULL != handle);
1478    BDBG_ASSERT(handle->allocated);
1479    BDBG_ASSERT(!handle->started);
1480
1481#ifdef BCHP_AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi_ARRAY_BASE
1482    /* Set input FCI */
1483    for ( i = 0; i < handle->numChannelPairs; i++ )
1484    {
1485        BAPE_IopStreamSettings streamSettings;
1486        unsigned streamId;
1487        streamId = GET_DUMMYSINK_STREAM_ID(handle->dummysinkIds[i]);
1488        BAPE_Iop_P_GetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1489        streamSettings.resolution = handle->settings.resolution;
1490        streamSettings.input = handle->settings.input.ids[i];
1491        errCode = BAPE_Iop_P_SetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1492        if ( errCode )
1493        {
1494            return BERR_TRACE(errCode);
1495        }
1496    }
1497
1498    /* Enable Dummysink */
1499    for ( i = 0; i < handle->numChannelPairs; i++ )
1500    {
1501        BDBG_MSG(("Enabling dummysink %u", handle->dummysinkIds[i]));
1502        regAddr = BCHP_AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi_ARRAY_BASE + (4*handle->dummysinkIds[i]);
1503        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1504        regVal &= ~BCHP_MASK(AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi, ENA);
1505        regVal |= BCHP_FIELD_DATA(AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi, ENA, 1);
1506        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1507    }
1508#else
1509    BSTD_UNUSED(errCode);
1510    BSTD_UNUSED(regVal);
1511    /* Newer 7429-style */
1512    for ( i = 0; i < handle->numChannelPairs; i++ )
1513    {
1514        BAPE_Reg_P_FieldList regFieldList;
1515
1516        /* Configure dummysink output interface */
1517        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, handle->dummysinkIds[i]);
1518        BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
1519        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, GROUP_ID, handle->dummysinkIds[0]);
1520        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, CHANNEL_GROUPING, 0xf>>(4-handle->numChannelPairs));
1521        switch ( handle->settings.resolution )
1522        {
1523        case 16: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_16_Bit); break;
1524        case 17: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_17_Bit); break;
1525        case 18: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_18_Bit); break;
1526        case 19: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_19_Bit); break;
1527        case 20: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_20_Bit); break;
1528        case 21: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_21_Bit); break;
1529        case 22: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_22_Bit); break;
1530        case 23: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_23_Bit); break;
1531        case 24: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, STREAM_BIT_RESOLUTION, Res_24_Bit); break;
1532        default: 
1533            BDBG_ERR(("Invalid loopback stream resolution (%u)", handle->settings.resolution)); 
1534            return BERR_TRACE(BERR_NOT_SUPPORTED);
1535        }
1536        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, FCI_ID, handle->settings.input.ids[i]);
1537        BAPE_Reg_P_ApplyFieldList(&regFieldList, regAddr);
1538    }
1539
1540    /* Enable the interface. */
1541    for ( i = 0; i < handle->numChannelPairs; i++ )
1542    {
1543        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, handle->dummysinkIds[i]);
1544        BAPE_Reg_P_UpdateField(handle->deviceHandle, regAddr, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, ENA, 1);
1545    }
1546#endif
1547
1548    handle->started = true;
1549
1550    return BERR_SUCCESS;
1551}
1552
1553void BAPE_DummysinkGroup_P_Stop(BAPE_DummysinkGroupHandle handle)
1554{
1555    BERR_Code errCode;
1556    uint32_t regAddr, regVal;
1557    unsigned i;
1558
1559    BDBG_ASSERT(NULL != handle);
1560    BDBG_ASSERT(handle->allocated);
1561    if ( !handle->started )
1562    {
1563        return;
1564    }
1565
1566#ifdef BCHP_AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi_ARRAY_BASE
1567    /* Disable Dummysink */
1568    for ( i = 0; i < handle->numChannelPairs; i++ )
1569    {
1570        BDBG_MSG(("Enabling dummysink %u", handle->dummysinkIds[i]));
1571        regAddr = BCHP_AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi_ARRAY_BASE + (4*handle->dummysinkIds[i]);
1572        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1573        regVal &= ~BCHP_MASK(AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi, ENA);
1574        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1575    }
1576
1577    /* Clear input FCI */
1578    for ( i = 0; i < handle->numChannelPairs; i++ )
1579    {
1580        BAPE_IopStreamSettings streamSettings;
1581        unsigned streamId;
1582        streamId = GET_DUMMYSINK_STREAM_ID(handle->dummysinkIds[i]);
1583        BAPE_Iop_P_GetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1584        streamSettings.input = BAPE_FCI_ID_INVALID;
1585        errCode = BAPE_Iop_P_SetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1586        BDBG_ASSERT(BERR_SUCCESS == errCode);
1587    }
1588#else
1589    BSTD_UNUSED(errCode);
1590    BSTD_UNUSED(regVal);
1591    /* Disable the interface */
1592    for ( i = 0; i < handle->numChannelPairs; i++ )
1593    {
1594        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, handle->dummysinkIds[i]);
1595        BAPE_Reg_P_UpdateField(handle->deviceHandle, regAddr, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, ENA, 0);
1596    }
1597
1598    /* Clear any grouping */
1599    for ( i = 0; i < handle->numChannelPairs; i++ )
1600    {
1601        BAPE_Reg_P_FieldList regFieldList;
1602
1603        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, handle->dummysinkIds[i]);
1604        BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
1605        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, GROUP_ID, handle->dummysinkIds[i]);
1606        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, CHANNEL_GROUPING, 1);
1607        BAPE_Reg_P_ApplyFieldList(&regFieldList, regAddr);
1608    }
1609#endif
1610
1611    handle->started = false;
1612}
1613
1614
1615BERR_Code BAPE_DummysinkGroup_P_ResumeFromStandby(BAPE_Handle bapeHandle)
1616{
1617    BERR_Code   errCode = BERR_SUCCESS;
1618    unsigned    i;
1619
1620    BDBG_OBJECT_ASSERT(bapeHandle, BAPE_Device);
1621
1622    /* For each opened DummysinkGroup, call the functions necessary to restore the hardware to it's appropriate state. */
1623    for ( i=0 ; i<BAPE_CHIP_MAX_DUMMYSINK_GROUPS ; i++ )
1624    {
1625        if ( bapeHandle->dummysinkGroups[i]->allocated )       /* If this one is open... */
1626        {
1627            BAPE_DummysinkGroupHandle hDummysinkGroup = bapeHandle->dummysinkGroups[i];
1628
1629            /* Put the HW into the generic open state. */
1630            errCode = BAPE_DummysinkGroup_P_OpenHw(hDummysinkGroup );
1631            if ( errCode ) return BERR_TRACE(errCode);
1632           
1633            /* Now apply changes for the settings struct. */
1634            errCode = BAPE_DummysinkGroup_P_SetSettings(hDummysinkGroup, &hDummysinkGroup->settings);
1635            if ( errCode ) return BERR_TRACE(errCode);
1636
1637            /* Now restore the dynamic stuff from the values saved in the device struct. */
1638                /* Nothing to do for this. */
1639        }
1640    }
1641    return errCode;
1642}
1643
1644
1645static BERR_Code BAPE_DummysinkGroup_P_OpenHw( BAPE_DummysinkGroupHandle hDummysinkGroup )
1646{
1647    unsigned i;
1648
1649    BDBG_ASSERT(NULL != hDummysinkGroup);
1650    BDBG_ASSERT(hDummysinkGroup->allocated);
1651
1652    for ( i = 0; i < hDummysinkGroup->numChannelPairs; i++ )
1653    {
1654        BAPE_Dummysink_P_SetGroup(hDummysinkGroup->deviceHandle, hDummysinkGroup->dummysinkIds[i], hDummysinkGroup->dummysinkIds[0], hDummysinkGroup->numChannelPairs);
1655    }
1656
1657    return BERR_SUCCESS;
1658}
1659
1660static void BAPE_Loopback_P_SetGroup(BAPE_Handle deviceHandle, uint32_t loopback, uint32_t group, uint32_t numChannelPairs)
1661{
1662    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1663    BDBG_ASSERT(loopback < BAPE_CHIP_MAX_LOOPBACKS);
1664    BDBG_ASSERT(group >= loopback);
1665    BDBG_ASSERT(group < BAPE_CHIP_MAX_LOOPBACKS);
1666
1667#ifdef BCHP_AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i_ARRAY_BASE
1668    {
1669        BAPE_Reg_P_FieldList regFieldList;
1670        uint32_t regAddr;
1671
1672        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, loopback);
1673        BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);
1674        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, GROUP_ID, group);
1675        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_LOOPBACK_0_STREAM_CFG_i, CHANNEL_GROUPING, 0xf>>(4-numChannelPairs));
1676        BAPE_Reg_P_ApplyFieldList(&regFieldList, regAddr);
1677
1678        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, loopback);
1679        BAPE_Reg_P_UpdateField(deviceHandle, regAddr, AUD_FMM_IOP_LOOPBACK_0_CAP_STREAM_CFG_i, CAP_GROUP_ID, group);
1680    }
1681#else
1682    BSTD_UNUSED(numChannelPairs);
1683#endif
1684}
1685
1686static void BAPE_Dummysink_P_SetGroup(BAPE_Handle deviceHandle, uint32_t dummysink, uint32_t group, uint32_t numChannelPairs)
1687{
1688    uint32_t regAddr;
1689
1690    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1691    BDBG_ASSERT(dummysink < BAPE_CHIP_MAX_DUMMYSINKS);
1692    BDBG_ASSERT(group >= dummysink);
1693    BDBG_ASSERT(group < BAPE_CHIP_MAX_DUMMYSINKS);
1694
1695#ifdef BCHP_AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi_ARRAY_BASE
1696    BSTD_UNUSED(numChannelPairs);
1697    regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi, dummysink);
1698    BAPE_Reg_P_UpdateField(deviceHandle, regAddr, AUD_FMM_IOP_CTRL_DUMMYSINK_CFGi, GROUP, group);
1699#else
1700    {
1701        BAPE_Reg_P_FieldList regFieldList;
1702
1703        regAddr = BAPE_Reg_P_GetArrayAddress(AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, dummysink);
1704        BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);
1705        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, GROUP_ID, group);
1706        BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_DUMMYSINK_0_STREAM_CFG_0_i, CHANNEL_GROUPING, 0xf>>(4-numChannelPairs));
1707        BAPE_Reg_P_ApplyFieldList(&regFieldList, regAddr);
1708    }
1709#endif
1710}
1711
Note: See TracBrowser for help on using the repository browser.