source: svn/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_i2s_output.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.8 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_i2s_output.c $
11 * $brcm_Revision: Hydra_Software_Devel/28 $
12 * $brcm_Date: 3/6/12 3:05p $
13 *
14 * Module Description: Audio Decoder Interface
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/ape/7422/bape_i2s_output.c $
19 *
20 * Hydra_Software_Devel/28   3/6/12 3:05p gskerl
21 * SW7425-2570: Renamed OutputPortObject substruct from connector to
22 * outputPort.
23 *
24 * Hydra_Software_Devel/27   11/14/11 3:37p gskerl
25 * SW7429-18: Merging 7429 changes back to main branch.
26 *
27 * Hydra_Software_Devel/SW7429-18/1   10/27/11 3:21p jgarrett
28 * SW7429-18: Adding I2S Output for 7429
29 *
30 * Hydra_Software_Devel/26   10/3/11 12:41p gskerl
31 * SW7231-129: Changed a call from BAPE_I2sOutput_SetSettings() to
32 * BAPE_I2sOutput_P_ApplySettings() with force=true. Also added an assert
33 * to BAPE_I2sOutput_Close().
34 *
35 * Hydra_Software_Devel/25   10/2/11 2:57p gskerl
36 * SW7231-129: Added stub function for
37 * BAPE_I2sOutput_P_ResumeFromStandby() (for when there are no I2S
38 * outputs)
39 *
40 * Hydra_Software_Devel/24   9/30/11 11:33a gskerl
41 * SW7231-129: Updated comments. Removed dead code.
42 *
43 * Hydra_Software_Devel/23   9/29/11 10:24a gskerl
44 * SW7231-129: Commented out #define of SETUP_PINMUX_FOR_I2S_OUT_ON_7425,
45 * which was inadvertently left defined
46 *
47 * Hydra_Software_Devel/22   9/28/11 5:42p gskerl
48 * SW7231-129: Added support for recovering hardware state after power
49 * standby/resume.
50 *
51 * Hydra_Software_Devel/21   9/7/11 10:36a sgadara
52 * SWDTV-8370: [35233] Correcting the IOP index retrieve for I2S Stereo 1
53 * port
54 *
55 * Hydra_Software_Devel/20   8/25/11 2:43p gskerl
56 * SW7425-1178: Changed name of conditional from
57 * SETUP_PINMUX_FOR_I2S_OUT_ON_7422 to SETUP_PINMUX_FOR_I2S_OUT_ON_7425.,
58 *
59 * Hydra_Software_Devel/18   7/8/11 6:38p jgarrett
60 * SWDTV-6760: Adding I2sMultiOutput
61 *
62 * Hydra_Software_Devel/17   7/8/11 4:25p gskerl
63 * SW7552-72: Added support for NCO/Mclkgen audio clock sources
64 *
65 * Hydra_Software_Devel/16   7/7/11 10:53a jgarrett
66 * SW7552-69: Added stereoMode setting
67 *
68 * Hydra_Software_Devel/15   5/20/11 5:16p jgarrett
69 * SW7425-402: Adding error code to handle output enable callback failing.
70 *
71 * Hydra_Software_Devel/14   5/3/11 10:49a gskerl
72 * SW7422-354: Added index and type args to APE_P_InitOutputPort macro
73 *
74 * Hydra_Software_Devel/13   4/16/11 12:15p jgarrett
75 * SW7425-371: Removing tab characters
76 *
77 * Hydra_Software_Devel/12   4/6/11 1:24a jgarrett
78 * SW35330-35: Merge to main branch
79 *
80 * Hydra_Software_Devel/SW35330-35/2   4/5/11 7:13p jgarrett
81 * SW35330-35: PCM Playback working on 35230
82 *
83 * Hydra_Software_Devel/SW35330-35/1   4/5/11 12:50p jgarrett
84 * SW35330-35: FMM Abstraction refactoring to support DTV
85 *
86 * Hydra_Software_Devel/11   3/22/11 3:10p gskerl
87 * SW7422-146: Changed audio output connector callbacks to take the output
88 * connector as an argument
89 *
90 * Hydra_Software_Devel/10   3/11/11 3:57p gskerl
91 * SW7422-146: Corrected and clarified some comments.
92 *
93 * Hydra_Software_Devel/9   2/22/11 5:43p jgarrett
94 * SW7422-146: Implemented type renaming based on filter graph review
95 * comments
96 *
97 * Hydra_Software_Devel/8   2/17/11 5:40p gskerl
98 * SW7422-146: Minor cosmetic cleanup.
99 *
100 * Hydra_Software_Devel/7   2/16/11 4:50p jgarrett
101 * SW7422-146: Coverity CID 252
102 *
103 * Hydra_Software_Devel/6   2/16/11 2:24p gskerl
104 * SW7422-146: Cleaned up, refactored, added support for changing I2S SCLK
105 * (bit clock) rate.
106 *
107 * Hydra_Software_Devel/5   2/11/11 7:31p gskerl
108 * SW7422-146: Corrected a few compiler warnings.  Corrected logic that
109 * sets the LRCLK polarity (it was reversed).
110 *
111 * Hydra_Software_Devel/4   2/10/11 5:45p gskerl
112 * SW7422-146: Changed calling sequence for the audio output setMclk_isr
113 * callbacks
114 *
115 * Hydra_Software_Devel/3   2/4/11 12:51p gskerl
116 * SW7422-146:Added stub functions to handle BAPE_CHIP_MAX_I2S_OUTPUTS ==
117 * 0 (no I2S outputs).
118 *
119 * Hydra_Software_Devel/2   2/3/11 5:01p gskerl
120 * SW7422-146:First pass at I2S output support.  BAPE_SclkRate_e128Fs is
121 * not yet supported.
122 *
123 * Hydra_Software_Devel/1   1/12/11 4:24p jgarrett
124 * SW7422-146: Adding additional APIs
125 *
126 ***************************************************************************/
127
128#include "bape.h"
129#include "bape_priv.h"
130
131BDBG_MODULE(bape_i2s_output);
132
133#if BAPE_CHIP_MAX_I2S_OUTPUTS > 0   /* If no I2S outputs, then skip all of this and just put in stub funcs at bottom of file. */
134
135BDBG_OBJECT_ID(BAPE_I2sOutput);
136
137typedef struct BAPE_I2sOutput
138{
139    BDBG_OBJECT(BAPE_I2sOutput)
140    BAPE_Handle deviceHandle;
141    BAPE_I2sOutputSettings settings;
142    unsigned index;
143    BAPE_OutputPortObject outputPort;
144    unsigned sampleRate;
145    uint32_t offset;
146    struct
147    {
148        BAPE_MclkSource mclkSource;
149        unsigned pllChannel;    /* only applies if mclkSource refers to a PLL */
150        unsigned mclkFreqToFsRatio;
151    } mclkInfo;
152    bool enabled;
153    char name[14];   /* I2s Output %d */
154} BAPE_I2sOutput;
155
156
157/* Static function prototypes */
158static void         BAPE_I2sOutput_P_UpdateMclkReg_isr(BAPE_I2sOutputHandle hI2sOutput );
159static BERR_Code    BAPE_I2sOutput_P_OpenHw(BAPE_I2sOutputHandle handle);
160static BERR_Code    BAPE_I2sOutput_P_CloseHw(BAPE_I2sOutputHandle handle);
161static BERR_Code    BAPE_I2sOutput_P_ApplySettings(BAPE_I2sOutputHandle handle,const BAPE_I2sOutputSettings *pSettings,bool force);
162
163/* Output port callbacks */
164static void BAPE_I2sOutput_P_SetTimingParams_isr(BAPE_OutputPort output, unsigned sampleRate, BAVC_Timebase timebase);
165static BERR_Code BAPE_I2sOutput_P_Enable(BAPE_OutputPort output);
166static void BAPE_I2sOutput_P_Disable(BAPE_OutputPort output);
167static void BAPE_I2sOutput_P_SetMclk_isr(BAPE_OutputPort output, BAPE_MclkSource mclkSource, unsigned pllChannel, unsigned mclkFreqToFsRatio);
168
169#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START
170#include "bchp_aud_fmm_iop_out_i2s_stereo_0.h"
171/* 7249-style chips */
172static void         BAPE_I2sOutput_P_UpdateMclkReg_IopOut_isr(BAPE_I2sOutputHandle hI2sOutput );
173static BERR_Code    BAPE_I2sOutput_P_OpenHw_IopOut(BAPE_I2sOutputHandle handle);
174static BERR_Code    BAPE_I2sOutput_P_CloseHw_IopOut(BAPE_I2sOutputHandle handle);
175static BERR_Code    BAPE_I2sOutput_P_ApplySettings_IopOut(BAPE_I2sOutputHandle handle,const BAPE_I2sOutputSettings *pSettings,bool force);
176static BERR_Code    BAPE_I2sOutput_P_Enable_IopOut(BAPE_OutputPort output);
177static void         BAPE_I2sOutput_P_Disable_IopOut(BAPE_OutputPort output);
178
179#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_1_REG_START
180#include "bchp_aud_fmm_iop_out_i2s_stereo_1.h"
181#define GET_I2S_OFFSET(idx) ((idx)*(BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_1_REG_START-BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START))
182#endif
183
184#else
185/* Legacy STB chips */
186static void         BAPE_I2sOutput_P_UpdateMclkReg_Legacy_isr(BAPE_I2sOutputHandle hI2sOutput );
187static BERR_Code    BAPE_I2sOutput_P_OpenHw_Legacy(BAPE_I2sOutputHandle handle);
188static BERR_Code    BAPE_I2sOutput_P_CloseHw_Legacy(BAPE_I2sOutputHandle handle);
189static BERR_Code    BAPE_I2sOutput_P_ApplySettings_Legacy(BAPE_I2sOutputHandle handle,const BAPE_I2sOutputSettings *pSettings,bool force);
190static BERR_Code    BAPE_I2sOutput_P_Enable_Legacy(BAPE_OutputPort output);
191static void         BAPE_I2sOutput_P_Disable_Legacy(BAPE_OutputPort output);
192
193#if BAPE_CHIP_MAX_I2S_OUTPUTS > 1
194    #define  GET_I2S_REG_ADDR2(prefix,idx)         (prefix##0         + (prefix##1         - prefix##0        ) * idx )
195    #define  GET_I2S_REG_ADDR3(prefix,idx,suffix)  (prefix##0##suffix + (prefix##1##suffix - prefix##0##suffix) * idx )
196
197    /* STB Chips */
198    #define  GET_I2S_OP_STREAM_ID(idx) ((idx) == 0 ? 7 : (idx) == 1 ? 8 : (BDBG_ASSERT(0), 0))
199    #define  GET_I2S_IOP_STREAM_ID(idx) GET_I2S_OP_STREAM_ID(idx) /* STB chips have this privilege */
200
201    #define  GET_I2S_CROSSBAR_ADDR(idx) (((idx) * (BCHP_AUD_FMM_OP_CTRL_I2SS1_CROSSBAR - BCHP_AUD_FMM_OP_CTRL_I2SS0_CROSSBAR)) + BCHP_AUD_FMM_OP_CTRL_I2SS0_CROSSBAR);
202#else
203    #define  GET_I2S_REG_ADDR2(prefix,idx       )  (prefix##0         )
204    #define  GET_I2S_REG_ADDR3(prefix,idx,suffix)  (prefix##0##suffix )
205    #define  GET_I2S_OP_STREAM_ID(idx) (7)     /* Holds true across all chips today */
206    #define  GET_I2S_IOP_STREAM_ID(idx) GET_I2S_OP_STREAM_ID(idx)
207    #define  GET_I2S_CROSSBAR_ADDR(idx) (BCHP_AUD_FMM_OP_CTRL_I2SS0_CROSSBAR);
208#endif
209#endif
210
211#ifndef GET_I2S_OFFSET
212#define GET_I2S_OFFSET(idx) (0)
213#endif
214
215/****  #define SETUP_PINMUX_FOR_I2S_OUT_ON_7425 ****/   /* Only defined for testing... changes pinmux settings. */
216#ifdef  SETUP_PINMUX_FOR_I2S_OUT_ON_7425
217    static void BAPE_I2sOutput_P_SetupPinmuxForI2sTesting( BAPE_Handle deviceHandle );
218    #warning "Compiling with special pinmux code to enable I2S outputs"
219#endif /* SETUP_PINMUX_FOR_I2S_OUT_ON_7425 */
220
221
222/***************************************************************************
223        Public APIs: From bape_output.h
224***************************************************************************/
225
226void BAPE_I2sOutput_GetDefaultSettings(
227    BAPE_I2sOutputSettings *pSettings
228    )
229{
230    BDBG_ASSERT(NULL != pSettings);
231    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
232
233    pSettings->stereoMode     = BAPE_StereoMode_eLeftRight;
234    pSettings->justification  = BAPE_I2sJustification_eMsbFirst;
235    pSettings->dataAlignment  = BAPE_I2sDataAlignment_eDelayed;
236    pSettings->lrPolarity     = BAPE_I2sLRClockPolarity_eLeftLow;
237    pSettings->sclkPolarity   = BAPE_I2sSclkPolarity_eFalling;
238    pSettings->sclkRate       = BAPE_SclkRate_e64Fs;
239}
240
241/**************************************************************************/
242
243BERR_Code BAPE_I2sOutput_Open(
244    BAPE_Handle deviceHandle,
245    unsigned index,
246    const BAPE_I2sOutputSettings *pSettings,
247    BAPE_I2sOutputHandle *pHandle             /* [out] */
248    )
249{
250    BERR_Code errCode;
251    BAPE_I2sOutputHandle handle;
252    BAPE_I2sOutputSettings defaultSettings;
253
254    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
255    BDBG_ASSERT(NULL != pHandle);
256
257    BDBG_MSG(("%s: Opening I2S Output: %u", __FUNCTION__, index));
258
259    *pHandle = NULL;    /* Set up to return null handle in case of error. */
260
261    if ( index >= BAPE_CHIP_MAX_I2S_OUTPUTS )
262    {
263        BDBG_ERR(("Request to open I2S output %d but chip only has %u I2S outputs", index, BAPE_CHIP_MAX_I2S_OUTPUTS));
264        return BERR_TRACE(BERR_INVALID_PARAMETER);
265    }
266
267    if ( deviceHandle->i2sOutputs[index] )
268    {
269        BDBG_ERR(("I2S output %d already open", index));
270        return BERR_TRACE(BERR_INVALID_PARAMETER);
271    }
272
273    #ifdef  SETUP_PINMUX_FOR_I2S_OUT_ON_7425
274        BAPE_I2sOutput_P_SetupPinmuxForI2sTesting(deviceHandle);
275    #endif /* SETUP_PINMUX_FOR_I2S_OUT_ON_7425 */
276
277    /* Allocate the device structure, then fill in all the fields. */
278    handle = BKNI_Malloc(sizeof(BAPE_I2sOutput));
279    if ( NULL == handle )
280    {
281        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
282    }
283
284    BKNI_Memset(handle, 0, sizeof(BAPE_I2sOutput));
285    BDBG_OBJECT_SET(handle, BAPE_I2sOutput);
286    handle->deviceHandle = deviceHandle;
287    handle->index = index;
288    handle->offset = GET_I2S_OFFSET(index);
289    BAPE_P_InitOutputPort(&handle->outputPort, BAPE_OutputPortType_eI2sOutput, index, handle);
290    handle->outputPort.maxChannelPairs = 1;  /* I2S output is stereo only */
291    handle->outputPort.mclkOutput = BAPE_MclkSource_eNone;
292    handle->outputPort.compressedSupported = false;
293    handle->outputPort.muteInMixer = true;
294    handle->outputPort.fsTiming = false;
295    handle->outputPort.pllRequired = true;
296
297/*  handle->connector.mixerId[]  leave at default */
298    handle->outputPort.setTimingParams_isr = BAPE_I2sOutput_P_SetTimingParams_isr;
299    handle->outputPort.setMclk_isr = BAPE_I2sOutput_P_SetMclk_isr;
300    handle->outputPort.setFs = NULL;         /* not used unless fsTiming == true */
301    handle->outputPort.setMute = NULL;
302    handle->outputPort.enable = BAPE_I2sOutput_P_Enable;
303    handle->outputPort.disable = BAPE_I2sOutput_P_Disable;
304/*  handle->connector.volume - leave at default */
305    BKNI_Snprintf(handle->name, sizeof(handle->name), "I2S Output %u", index);
306    handle->outputPort.pName = handle->name;
307
308    /* Setup to 48k, muted by default */
309    BKNI_EnterCriticalSection();
310    BAPE_I2sOutput_P_SetTimingParams_isr(&handle->outputPort, 48000, BAVC_Timebase_e0);
311    BKNI_LeaveCriticalSection();
312
313    /* Init to specified settings */
314    if ( NULL == pSettings )
315    {
316        BAPE_I2sOutput_GetDefaultSettings(&defaultSettings);
317        pSettings = &defaultSettings;
318    }
319                   
320    errCode = BAPE_I2sOutput_P_OpenHw(handle);
321    if ( errCode )
322    {
323        BAPE_I2sOutput_Close(handle);
324        return BERR_TRACE(errCode);
325    }
326
327    /* Initialize hardware before applying settings */
328    BKNI_EnterCriticalSection();
329    BAPE_I2sOutput_P_SetMclk_isr(&handle->outputPort, BAPE_MclkSource_ePll0, 0, BAPE_BASE_PLL_TO_FS_RATIO);
330    BKNI_LeaveCriticalSection();   
331                   
332    errCode = BAPE_I2sOutput_P_ApplySettings(handle, pSettings, true);   /* true => force update of HW */
333    if ( errCode )
334    {
335        BAPE_I2sOutput_Close(handle);
336        return BERR_TRACE(errCode);
337    }
338                       
339    *pHandle = handle;
340    handle->deviceHandle->i2sOutputs[index] = handle;
341    return BERR_SUCCESS;
342}
343
344/**************************************************************************/
345
346void BAPE_I2sOutput_Close(
347    BAPE_I2sOutputHandle handle
348    )
349{
350    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
351
352    /* Make sure we're not still connected to anything */
353    if ( handle->outputPort.mixer )
354    {
355        BDBG_ERR(("Cannot close I2S output %p (%s), still connected to mixer %p", handle, handle->name, handle->outputPort.mixer));
356        BDBG_ASSERT(NULL == handle->outputPort.mixer);
357        return;
358    }
359
360    BAPE_I2sOutput_P_CloseHw(handle);
361
362    BDBG_ASSERT(handle->index < BAPE_CHIP_MAX_I2S_OUTPUTS);
363    handle->deviceHandle->i2sOutputs[handle->index] = NULL;
364    BDBG_OBJECT_DESTROY(handle, BAPE_I2sOutput);
365    BKNI_Free(handle);   
366}
367
368/**************************************************************************/
369
370void BAPE_I2sOutput_GetSettings(
371    BAPE_I2sOutputHandle handle,
372    BAPE_I2sOutputSettings *pSettings     /* [out] */
373    )
374{
375    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
376    BDBG_ASSERT(NULL != pSettings);
377    *pSettings = handle->settings;
378}
379
380/**************************************************************************/
381
382BERR_Code BAPE_I2sOutput_SetSettings(
383    BAPE_I2sOutputHandle handle,
384    const BAPE_I2sOutputSettings *pSettings
385    )
386{
387    BERR_Code   errCode = BERR_SUCCESS;
388
389    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
390    BDBG_ASSERT(NULL != pSettings);
391
392    errCode = BAPE_I2sOutput_P_ApplySettings(handle, pSettings, false); /* false => don't force (only update HW for changes) */
393    return errCode;
394}
395
396/**************************************************************************/
397
398void BAPE_I2sOutput_GetOutputPort(
399    BAPE_I2sOutputHandle handle,
400    BAPE_OutputPort *pOutputPort        /* [out] */
401    )
402{
403    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
404    BDBG_ASSERT(NULL != pOutputPort);
405    *pOutputPort = &handle->outputPort;
406}
407
408/***************************************************************************
409        BAPE Internal APIs: From bape_fmm_priv.h
410***************************************************************************/
411
412BERR_Code BAPE_I2sOutput_P_ResumeFromStandby(BAPE_Handle bapeHandle)
413{
414    BERR_Code   errCode = BERR_SUCCESS;
415    unsigned    i2sOutputIndex;
416
417    BDBG_OBJECT_ASSERT(bapeHandle, BAPE_Device);
418
419    /* For each opened I2sOutput, call the functions necessary to restore the hardware to it's appropriate state. */
420    for ( i2sOutputIndex=0 ; i2sOutputIndex<BAPE_CHIP_MAX_I2S_OUTPUTS ; i2sOutputIndex++ )
421    {
422        if ( bapeHandle->i2sOutputs[i2sOutputIndex] )       /* If this I2sOutput is open... */
423        {
424            BAPE_I2sOutputHandle hI2sOutput = bapeHandle->i2sOutputs[i2sOutputIndex];
425
426            /* Put the HW into the generic open state. */
427            errCode = BAPE_I2sOutput_P_OpenHw(hI2sOutput);
428            if ( errCode ) return BERR_TRACE(errCode);
429           
430            /* Now apply changes for the settings struct. */
431            errCode = BAPE_I2sOutput_P_ApplySettings(hI2sOutput, &hI2sOutput->settings, true);   /* true => force update of HW */
432            if ( errCode ) return BERR_TRACE(errCode);
433
434            /* Now restore the dynamic stuff from the values saved in the device struct. */
435            BKNI_EnterCriticalSection();
436
437                BAPE_I2sOutput_P_SetTimingParams_isr(&hI2sOutput->outputPort, 
438                                                     hI2sOutput->sampleRate, 
439                                                     0);    /* timebase is unused, 0 is dummy value */
440                BAPE_I2sOutput_P_UpdateMclkReg_isr(hI2sOutput);
441            BKNI_LeaveCriticalSection();
442        }
443    }
444    return errCode;
445}
446
447
448/***************************************************************************
449        Private callbacks: Protyped above
450***************************************************************************/
451
452static void BAPE_I2sOutput_P_SetTimingParams_isr(BAPE_OutputPort output, unsigned sampleRate, BAVC_Timebase timebase)
453{
454    BAPE_I2sOutputHandle handle;
455
456    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
457
458    handle = output->pHandle;
459    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
460    BSTD_UNUSED(timebase);  /* I2s doesn't care */
461
462    handle->sampleRate = sampleRate;
463}
464
465/**************************************************************************/
466
467static BERR_Code BAPE_I2sOutput_P_Enable(BAPE_OutputPort output)
468{
469#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START
470    return BAPE_I2sOutput_P_Enable_IopOut(output);
471#else
472    return BAPE_I2sOutput_P_Enable_Legacy(output);
473#endif
474}
475
476/**************************************************************************/
477
478static void BAPE_I2sOutput_P_Disable(BAPE_OutputPort output)
479{
480#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START
481    BAPE_I2sOutput_P_Disable_IopOut(output);
482#else
483    BAPE_I2sOutput_P_Disable_Legacy(output);
484#endif
485}
486
487/**************************************************************************/
488
489static void BAPE_I2sOutput_P_SetMclk_isr(BAPE_OutputPort output, BAPE_MclkSource mclkSource, unsigned pllChannel, unsigned mclkFreqToFsRatio)
490{
491    BAPE_I2sOutputHandle handle;
492
493    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
494
495    handle = output->pHandle;
496    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
497
498    /* Just do some validation, then set the new values in the handle's mclkInfo struct.
499     * Then ...UpdateMclkReg_isr() will take it from  there.
500     */
501    if (BAPE_MCLKSOURCE_IS_PLL(mclkSource) )
502    {
503        handle->mclkInfo.mclkSource = mclkSource;
504        handle->mclkInfo.pllChannel = pllChannel;
505    }
506    else  if ( BAPE_MCLKSOURCE_IS_DAC(mclkSource) )
507    {
508        handle->mclkInfo.mclkSource = mclkSource;
509        handle->mclkInfo.pllChannel = 0;
510
511        BDBG_WRN(("DAC timing source has been selected for I2S output %u.", handle->index));
512        BDBG_WRN(("It is strongly recommended to place I2S and DAC outputs on separate mixers."));
513    }
514    else  if ( BAPE_MCLKSOURCE_IS_NCO(mclkSource) )
515    {
516        handle->mclkInfo.mclkSource = mclkSource;
517        handle->mclkInfo.pllChannel = 0;
518
519        BDBG_WRN(("NCO timing source has been selected for I2S output %u.", handle->index));
520        BDBG_WRN(("It is strongly recommended to use PLL timing for I2S."));
521    }
522    /* mclkSource is not a valid PLL and not a valid DAC... give up. */
523    else
524    {
525        BDBG_ERR(("mclkSource (%u) doesn't refer to a valid PLL or DAC", mclkSource));
526        BDBG_ASSERT(false);     /* something went wrong somewhere! */
527        return;
528    }
529
530    handle->mclkInfo.mclkFreqToFsRatio = mclkFreqToFsRatio;
531
532    BAPE_I2sOutput_P_UpdateMclkReg_isr( handle );
533
534    return;
535}
536
537/***************************************************************************
538        Private functions: Protyped above
539***************************************************************************/
540static void         BAPE_I2sOutput_P_UpdateMclkReg_isr(BAPE_I2sOutputHandle hI2sOutput )
541{
542#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START
543    BAPE_I2sOutput_P_UpdateMclkReg_IopOut_isr(hI2sOutput);
544#else
545    BAPE_I2sOutput_P_UpdateMclkReg_Legacy_isr(hI2sOutput);
546#endif
547}
548
549static BERR_Code    BAPE_I2sOutput_P_OpenHw(BAPE_I2sOutputHandle handle)
550{
551#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START
552    return BAPE_I2sOutput_P_OpenHw_IopOut(handle);
553#else
554    return BAPE_I2sOutput_P_OpenHw_Legacy(handle);
555#endif   
556}
557
558static BERR_Code    BAPE_I2sOutput_P_CloseHw(BAPE_I2sOutputHandle handle)
559{
560#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START
561    return BAPE_I2sOutput_P_CloseHw_IopOut(handle);
562#else
563    return BAPE_I2sOutput_P_CloseHw_Legacy(handle);
564#endif   
565}
566
567static BERR_Code    BAPE_I2sOutput_P_ApplySettings(BAPE_I2sOutputHandle handle,const BAPE_I2sOutputSettings *pSettings,bool force)
568{
569#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START
570    return BAPE_I2sOutput_P_ApplySettings_IopOut(handle, pSettings, force);
571#else
572    return BAPE_I2sOutput_P_ApplySettings_Legacy(handle, pSettings, force);
573#endif   
574}
575
576#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_REG_START
577/* 7429 style chips */
578static void BAPE_I2sOutput_P_UpdateMclkReg_IopOut_isr(BAPE_I2sOutputHandle hI2sOutput )
579{
580    /* Use the values in the handle's mclkInfo struct to update the
581     * MCLK_CFG register.  */
582
583    BAPE_MclkSource      mclkSource          = hI2sOutput->mclkInfo.mclkSource;
584    unsigned             pllChannel          = hI2sOutput->mclkInfo.pllChannel;
585    unsigned             mclkFreqToFsRatio   = hI2sOutput->mclkInfo.mclkFreqToFsRatio;
586    BAPE_Reg_P_FieldList regFieldList;
587
588    BDBG_OBJECT_ASSERT(hI2sOutput, BAPE_I2sOutput);
589
590    BAPE_Reg_P_InitFieldList(hI2sOutput->deviceHandle, &regFieldList);
591
592    switch ( mclkSource )
593    {
594#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0_PLLCLKSEL_PLL0_ch1
595    case BAPE_MclkSource_ePll0:
596        switch ( pllChannel )
597        {
598        case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL0_ch1); break;
599        case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL0_ch2); break;
600        case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL0_ch3); break;               
601        default: (void) BERR_TRACE(BERR_NOT_SUPPORTED); break;
602        }
603        break;
604#endif
605#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0_PLLCLKSEL_PLL1_ch1
606    case BAPE_MclkSource_ePll1:
607        switch ( pllChannel )
608        {
609        case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL1_ch1); break;
610        case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL1_ch2); break;
611        case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL1_ch3); break;               
612        default: (void) BERR_TRACE(BERR_NOT_SUPPORTED); break;
613        }
614        break;
615#endif
616#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0_PLLCLKSEL_PLL2_ch1
617    case BAPE_MclkSource_ePll2:
618        switch ( pllChannel )
619        {
620        case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL2_ch1); break;
621        case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL2_ch2); break;
622        case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, PLL2_ch3); break;               
623        default: (void) BERR_TRACE(BERR_NOT_SUPPORTED); break;
624        }
625        break;
626#endif
627#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0_PLLCLKSEL_Mclk_gen0
628    case BAPE_MclkSource_eNco0:
629        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, Mclk_gen0); 
630        break;
631#endif
632#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0_PLLCLKSEL_Mclk_gen1
633    case BAPE_MclkSource_eNco1:
634        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, Mclk_gen1); 
635        break;
636#endif
637#ifdef BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0_PLLCLKSEL_Mclk_gen2
638    case BAPE_MclkSource_eNco2:
639        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, PLLCLKSEL, Mclk_gen2); 
640        break;
641#endif
642    default:
643        BDBG_ERR(("Unsupported clock source %u for MAI %u", mclkSource, hI2sOutput->index));
644        (void)BERR_TRACE(BERR_NOT_SUPPORTED);
645    }
646
647    switch ( mclkFreqToFsRatio )
648    {
649    case 128: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, MCLK_RATE, MCLK_128fs_SCLK_64fs); break;
650    case 256: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, MCLK_RATE, MCLK_256fs_SCLK_64fs); break;
651    case 384: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, MCLK_RATE, MCLK_384fs_SCLK_64fs); break;
652    case 512: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0, MCLK_RATE, MCLK_512fs_SCLK_64fs); break;
653    default:
654        BDBG_ERR(("Unsupported MCLK Rate of %uFs", mclkFreqToFsRatio));
655        (void)BERR_TRACE(BERR_NOT_SUPPORTED);
656        break;
657    }
658    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_MCLK_CFG_0 + hI2sOutput->offset);
659}
660
661static BERR_Code BAPE_I2sOutput_P_OpenHw_IopOut(BAPE_I2sOutputHandle handle)
662{
663    BAPE_Reg_P_FieldList regFieldList;
664    BERR_Code            errCode = BERR_SUCCESS;
665    BAPE_Handle          deviceHandle;
666    unsigned             index;
667
668    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
669
670    deviceHandle = handle->deviceHandle;
671    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
672
673    index = handle->index;
674
675    /* Enable the clock and data while opening the output port. Never disable it */
676    BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);
677    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, CLOCK_ENABLE, Enable);
678    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, DATA_ENABLE, Enable);
679    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG + handle->offset);
680
681    /* Turn on the I2S outputs  */
682    BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);   
683
684    if (index == 0)
685    {
686        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, SDATS0_OE, Drive);
687        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, SCLKS0_OE, Drive);
688        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, LRCKS0_OE, Drive);
689        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, MCLKS0_OE, Drive);
690    }
691    #if BAPE_CHIP_MAX_I2S_OUTPUTS > 1
692    else if(index == 1)
693    {
694        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, SDATS1_OE, Drive);
695        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, SCLKS1_OE, Drive);
696        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, LRCKS1_OE, Drive);
697        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, MCLKS1_OE, Drive);
698    }
699    #endif
700    #if BAPE_CHIP_MAX_I2S_OUTPUTS > 2
701        #error "Need to support more I2S outputs"
702    #endif
703
704    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_MISC_SEROUT_OE);
705
706    return errCode;
707}
708
709static BERR_Code BAPE_I2sOutput_P_CloseHw_IopOut(BAPE_I2sOutputHandle handle)
710{
711    BAPE_Reg_P_FieldList regFieldList;
712    BERR_Code            errCode = BERR_SUCCESS;
713    BAPE_Handle          deviceHandle;
714    unsigned             index;
715
716    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
717
718    deviceHandle = handle->deviceHandle;
719    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
720
721    index = handle->index;
722
723    /* Turn off the I2S outputs  */
724    BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);   
725
726    if (index == 0)
727    {
728        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, SDATS0_OE, Tristate);
729        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, SCLKS0_OE, Tristate);
730        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, LRCKS0_OE, Tristate);
731        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, MCLKS0_OE, Tristate);
732    }
733    #if BAPE_CHIP_MAX_I2S_OUTPUTS > 1
734    else if(index == 1)
735    {
736        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, SDATS1_OE, Tristate);
737        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, SCLKS1_OE, Tristate);
738        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, LRCKS1_OE, Tristate);
739        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_MISC_SEROUT_OE, MCLKS1_OE, Tristate);
740    }
741    #endif
742    #if BAPE_CHIP_MAX_I2S_OUTPUTS > 2
743        #error "Need to support more I2S outputs"
744    #endif
745
746    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_MISC_SEROUT_OE);
747
748    /* Enable the clock and data while opening the output port. Never disable it */
749    BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);
750    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, CLOCK_ENABLE, Disable);
751    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, DATA_ENABLE, Disable);
752    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG + handle->offset);
753
754    return errCode;
755}
756
757static BERR_Code BAPE_I2sOutput_P_ApplySettings_IopOut(
758    BAPE_I2sOutputHandle handle,
759    const BAPE_I2sOutputSettings *pSettings,
760    bool force
761    )
762{
763    BAPE_Reg_P_FieldList regFieldList;
764
765    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
766    BDBG_ASSERT(NULL != pSettings);
767
768    BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
769
770    switch ( pSettings->justification )
771    {
772    case BAPE_I2sJustification_eMsbFirst:
773        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, DATA_JUSTIFICATION, MSB);
774        break;
775    case BAPE_I2sJustification_eLsbFirst:
776        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, DATA_JUSTIFICATION, LSB);
777        break;
778    default:
779        BDBG_ERR(("Invalid value for BAPE_I2sOutputSettings.justification: %u", pSettings->justification ));
780        return BERR_TRACE(BERR_INVALID_PARAMETER);
781    }
782
783    switch ( pSettings->dataAlignment )
784    {
785    case BAPE_I2sDataAlignment_eDelayed:
786        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, DATA_ALIGNMENT, Delayed);
787        break;
788    case BAPE_I2sDataAlignment_eAligned:
789        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, DATA_ALIGNMENT, Aligned);
790        break;
791    default:
792        BDBG_ERR(("Invalid value for BAPE_I2sOutputSettings.dataAlignment: %u", pSettings->dataAlignment ));
793        return BERR_TRACE(BERR_INVALID_PARAMETER);
794    }
795
796    switch ( pSettings->lrPolarity )
797    {
798    case BAPE_I2sLRClockPolarity_eLeftLow:
799        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, LRCK_POLARITY, Low_for_left);
800        break;
801    case BAPE_I2sLRClockPolarity_eLeftHigh:
802        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, LRCK_POLARITY, High_for_left);
803        break;
804    default:
805        BDBG_ERR(("Invalid value for BAPE_I2sOutputSettings.lrPolarity: %u", pSettings->lrPolarity ));
806        return BERR_TRACE(BERR_INVALID_PARAMETER);
807    }
808
809    /*  Since setting the sclkRate involves updating two registers, only bother with this
810     *  if somebody is actually changing it.
811     */
812    if (pSettings->sclkRate != handle->settings.sclkRate || force)
813    {
814        switch ( pSettings->sclkRate )
815        {
816        case BAPE_SclkRate_e64Fs:
817            BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, SCLKS_PER_1FS_DIV32, 2);
818            break;
819        case BAPE_SclkRate_e128Fs:
820            BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, SCLKS_PER_1FS_DIV32, 4);
821            break;
822        default:
823            BDBG_ERR(("Invalid value for BAPE_I2sOutputSettings.sclkRate: %u", pSettings->sclkRate ));
824            return BERR_TRACE(BERR_INVALID_PARAMETER);
825        }
826
827        /* Set the new sclkRate into the settings struct so that ..._UpdateMclkReg_isr()
828         * will be able to use it.
829         */
830        handle->settings.sclkRate = pSettings->sclkRate;
831
832        /* Now update the MCLK_CONFIG register.  */
833        BKNI_EnterCriticalSection();
834        BAPE_I2sOutput_P_UpdateMclkReg_isr( handle );
835        BKNI_LeaveCriticalSection();
836    }
837
838    /* We only support 24 bits per sample. */
839    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG, BITS_PER_SAMPLE, Bitwidth24);
840
841    /* Apply register changes */
842    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG + handle->offset);
843
844    if ( pSettings->stereoMode != handle->settings.stereoMode || force )
845    {
846        BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
847        switch ( pSettings->stereoMode )
848        {
849        default:
850        case BAPE_StereoMode_eLeftRight:
851            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CROSSBAR, OUT_L, In_l);
852            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CROSSBAR, OUT_R, In_r);
853            break;
854        case BAPE_StereoMode_eLeftLeft:
855            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CROSSBAR, OUT_L, In_l);
856            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CROSSBAR, OUT_R, In_l);
857            break;
858        case BAPE_StereoMode_eRightRight:
859            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CROSSBAR, OUT_L, In_r);
860            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CROSSBAR, OUT_R, In_r);
861            break;
862        case BAPE_StereoMode_eRightLeft:
863            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CROSSBAR, OUT_L, In_r);
864            BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CROSSBAR, OUT_R, In_l);
865            break;           
866        }
867
868        /* Apply register changes */
869        BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_I2S_CFG + handle->offset);
870
871        handle->settings.stereoMode = pSettings->stereoMode;
872    }
873
874    handle->settings = *pSettings;
875
876    return BERR_SUCCESS;
877}
878
879static BERR_Code BAPE_I2sOutput_P_Enable_IopOut(BAPE_OutputPort output)
880{
881    BAPE_I2sOutputHandle handle;
882    BAPE_Reg_P_FieldList regFieldList;
883
884    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
885
886    handle = output->pHandle;
887    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
888
889    BDBG_ASSERT(false == handle->enabled);
890
891    /* Setup Interface */
892    BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
893    BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0, CHANNEL_GROUPING, 1);
894    BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0, GROUP_ID, 0);
895    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0, STREAM_BIT_RESOLUTION, Res_24_Bit);
896    BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0, FCI_ID, output->sourceMixerFci.ids[BAPE_ChannelPair_eLeftRight]);
897    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0 + handle->offset);
898
899    /* Enable the interface */
900    BAPE_Reg_P_UpdateField(handle->deviceHandle, 
901                           BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0 + handle->offset,
902                           AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0,
903                           ENA,
904                           1);
905
906    handle->enabled = true;
907
908    return BERR_SUCCESS;
909}
910
911/**************************************************************************/
912
913static void BAPE_I2sOutput_P_Disable_IopOut(BAPE_OutputPort output)
914{
915    BAPE_I2sOutputHandle handle;
916
917    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
918
919    handle = output->pHandle;
920    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
921
922    /* Disable the interface */
923    BAPE_Reg_P_UpdateField(handle->deviceHandle, 
924                           BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0 + handle->offset,
925                           AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0,
926                           ENA,
927                           0);
928
929    /* Clear the input value */
930    BAPE_Reg_P_UpdateField(handle->deviceHandle, 
931                           BCHP_AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0 + handle->offset,
932                           AUD_FMM_IOP_OUT_I2S_STEREO_0_STREAM_CFG_0,
933                           FCI_ID,
934                           BAPE_FCI_ID_INVALID);
935
936
937    handle->enabled = false;
938}
939
940#else
941/* Legacy STB chips */
942static void BAPE_I2sOutput_P_UpdateMclkReg_Legacy_isr(BAPE_I2sOutputHandle hI2sOutput )
943{
944    /* Use the values in the handle's mclkInfo struct to update the
945     * MCLK_CFG register.  */
946
947    BAPE_MclkSource     mclkSource          = hI2sOutput->mclkInfo.mclkSource;
948    unsigned            pllChannel          = hI2sOutput->mclkInfo.pllChannel;
949    unsigned            mclkFreqToFsRatio   = hI2sOutput->mclkInfo.mclkFreqToFsRatio;
950
951    uint32_t regAddr;
952    uint32_t regVal;
953    uint32_t mclkRate;
954    uint32_t pllclksel;
955
956    BDBG_OBJECT_ASSERT(hI2sOutput, BAPE_I2sOutput);
957
958    /* We need to determine new values for the MCLK_RATE and PLLCLKSEL fields of the
959     * AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO<n> register.
960     */ 
961    switch ( mclkSource )
962    {
963    /* PLL Timing */
964    #if BAPE_CHIP_MAX_PLLS > 0
965    case BAPE_MclkSource_ePll0:
966        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_PLL0_ch1 + pllChannel;
967        break;
968    #endif
969    #if BAPE_CHIP_MAX_PLLS > 1
970    case BAPE_MclkSource_ePll1:
971        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_PLL1_ch1 + pllChannel;
972        break;
973    #endif
974    #if BAPE_CHIP_MAX_PLLS > 2
975    case BAPE_MclkSource_ePll2:
976        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_PLL2_ch1 + pllChannel;
977        break;
978    #endif
979   
980    /* DAC Timing */
981    #if BAPE_CHIP_MAX_DACS > 0
982    case BAPE_MclkSource_eHifidac0:
983        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_Hifidac0;
984        break;
985    #endif
986    #if BAPE_CHIP_MAX_DACS > 1
987    case BAPE_MclkSource_eHifidac1:
988        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_Hifidac1;
989        break;
990    #endif
991    #if BAPE_CHIP_MAX_DACS > 2
992    case BAPE_MclkSource_eHifidac2:
993        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_Hifidac2;
994        break;
995    #endif
996   
997    /* NCO Timing */
998    #if BAPE_CHIP_MAX_NCOS > 0
999    case BAPE_MclkSource_eNco0:
1000        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_Mclk_gen0;
1001        break;
1002    #endif
1003    #if BAPE_CHIP_MAX_NCOS > 1
1004    case BAPE_MclkSource_eNco1:
1005        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_Mclk_gen1;
1006        break;
1007    #endif
1008    #if BAPE_CHIP_MAX_NCOS > 2
1009    case BAPE_MclkSource_eNco2:
1010        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0_PLLCLKSEL_Mclk_gen2;
1011        break;
1012    #endif
1013   
1014    /* Should never get here */
1015    default:
1016        BDBG_ERR(("mclkSource (%u) doesn't refer to a valid PLL or DAC", mclkSource));
1017        BDBG_ASSERT(false);     /* something went wrong somewhere! */
1018        return;
1019    }
1020
1021    /* Compute the value for the MCLK_RATE */
1022    switch ( hI2sOutput->settings.sclkRate )
1023    {
1024    case BAPE_SclkRate_e64Fs:
1025        mclkRate = mclkFreqToFsRatio / ( 2 * 64 );
1026        break;
1027
1028        /* Add code for this after we increase the base PLL rates. */
1029    case BAPE_SclkRate_e128Fs:
1030        mclkRate = mclkFreqToFsRatio / ( 2 * 128 );
1031        break;
1032
1033    default:
1034        BDBG_ASSERT(false); /* Should never get here */
1035        return;
1036    }
1037
1038    BDBG_ASSERT(mclkRate > 0); /* If this happens, might need to increase BAPE_BASE_PLL_TO_FS_RATIO */
1039
1040    /* We have the values in "pllclksel" and "mclkRate", now write to the registers. */
1041
1042    /* Choose the register for the appropriate output. */
1043    regAddr = GET_I2S_REG_ADDR2(BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO, hI2sOutput->index);
1044
1045    /* Read the register and clear the fields that we're going to fill in. */
1046    regVal = BREG_Read32_isr(hI2sOutput->deviceHandle->regHandle, regAddr);
1047    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0, PLLCLKSEL)|
1048                BCHP_MASK(AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0, MCLK_RATE));
1049
1050    /* Fill in the MCLK_RATE and PLLCLKSEL fields. */
1051    regVal |= BCHP_FIELD_DATA(AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0, MCLK_RATE, mclkRate);
1052    regVal |= BCHP_FIELD_DATA(AUD_FMM_OP_CTRL_MCLK_CFG_I2S_STEREO0, PLLCLKSEL, pllclksel);
1053
1054    /* Then write it to the reg. */
1055    BREG_Write32_isr(hI2sOutput->deviceHandle->regHandle, regAddr, regVal);
1056}
1057
1058/**************************************************************************/
1059
1060static BERR_Code BAPE_I2sOutput_P_OpenHw_Legacy(BAPE_I2sOutputHandle handle)
1061{
1062    BERR_Code       errCode = BERR_SUCCESS;
1063    BAPE_Handle     deviceHandle;
1064    uint32_t        regAddr, regVal;
1065    unsigned        index;
1066
1067    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
1068
1069    deviceHandle = handle->deviceHandle;
1070    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1071
1072    index = handle->index;
1073
1074    /* Enable the clock and data while opening the output port. Never disable it */
1075    regAddr = GET_I2S_REG_ADDR3(BCHP_AUD_FMM_OP_CTRL_I2SS, index, _CFG);
1076    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1077    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, CLOCK_ENABLE)|
1078                BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_ENABLE));
1079    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, CLOCK_ENABLE, Enable);
1080    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_ENABLE, Enable);
1081    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1082
1083    /* Turn on the I2S outputs  */
1084    regAddr = BCHP_AUD_FMM_MISC_SEROUT_OE;
1085    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1086
1087    if (index == 0)
1088    {
1089        regVal &= ~(
1090            #ifdef BCHP_AUD_FMM_MISC_SEROUT_OE_EXTI2SS0_MCLK_OE_MASK
1091                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,EXTI2SS0_MCLK_OE) |
1092            #endif
1093                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,LRCKS0_OE) |
1094                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,SCLKS0_OE) |
1095                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,SDATS0_OE));
1096
1097        #ifdef BCHP_AUD_FMM_MISC_SEROUT_OE_EXTI2SS0_MCLK_OE_MASK
1098            regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,EXTI2SS0_MCLK_OE, Drive));
1099        #endif
1100        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,LRCKS0_OE, Drive));           
1101        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,SCLKS0_OE, Drive));           
1102        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,SDATS0_OE, Drive));
1103    }
1104    #if BAPE_CHIP_MAX_I2S_OUTPUTS > 1
1105    else if(index == 1)
1106    {
1107        regVal &= ~(
1108            #ifdef BCHP_AUD_FMM_MISC_SEROUT_OE_EXTI2SS1_MCLK_OE_MASK
1109                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,EXTI2SS1_MCLK_OE) |
1110            #endif
1111                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,LRCKS1_OE) |
1112                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,SCLKS1_OE) |
1113                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,SDATS1_OE));
1114
1115        #ifdef BCHP_AUD_FMM_MISC_SEROUT_OE_EXTI2SS1_MCLK_OE_MASK
1116            regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,EXTI2SS1_MCLK_OE, Drive));
1117        #endif
1118        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,LRCKS1_OE, Drive));           
1119        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,SCLKS1_OE, Drive));           
1120        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,SDATS1_OE, Drive));
1121    }
1122    #endif
1123    #if BAPE_CHIP_MAX_I2S_OUTPUTS > 2
1124        #error "Need to support more I2S outputs"
1125    #endif
1126    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1127
1128    return errCode;
1129}
1130
1131/**************************************************************************/
1132
1133static BERR_Code BAPE_I2sOutput_P_CloseHw_Legacy(BAPE_I2sOutputHandle handle)
1134{
1135    BERR_Code       errCode = BERR_SUCCESS;
1136    BAPE_Handle     deviceHandle;
1137    uint32_t        regAddr, regVal;
1138    unsigned        index;
1139
1140    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
1141
1142    deviceHandle = handle->deviceHandle;
1143    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1144
1145    index = handle->index;
1146
1147    /* Put the I2S outputs into a high-Z state */
1148    regAddr = BCHP_AUD_FMM_MISC_SEROUT_OE;
1149    regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1150    if (handle->index == 0)
1151    {
1152        regVal &= ~(
1153            #ifdef BCHP_AUD_FMM_MISC_SEROUT_OE_EXTI2SS0_MCLK_OE_MASK
1154                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,EXTI2SS0_MCLK_OE) |
1155            #endif
1156                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,LRCKS0_OE) |
1157                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,SCLKS0_OE) |
1158                    BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,SDATS0_OE));
1159
1160        #ifdef BCHP_AUD_FMM_MISC_SEROUT_OE_EXTI2SS0_MCLK_OE_MASK
1161            regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,EXTI2SS0_MCLK_OE, Tristate));
1162        #endif
1163        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,LRCKS0_OE, Tristate));
1164        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,SCLKS0_OE, Tristate));
1165        regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,SDATS0_OE, Tristate));
1166    }
1167    #if BAPE_CHIP_MAX_I2S_OUTPUTS > 1
1168        else if(handle->index == 1)
1169        {
1170            regVal &= ~(
1171                #ifdef BCHP_AUD_FMM_MISC_SEROUT_OE_EXTI2SS1_MCLK_OE_MASK
1172                        BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,EXTI2SS1_MCLK_OE) |
1173                #endif
1174                        BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,LRCKS1_OE) |
1175                        BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,SCLKS1_OE) |
1176                        BCHP_MASK(AUD_FMM_MISC_SEROUT_OE,SDATS1_OE));
1177
1178            #ifdef BCHP_AUD_FMM_MISC_SEROUT_OE_EXTI2SS1_MCLK_OE_MASK
1179                regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,EXTI2SS1_MCLK_OE, Tristate));
1180            #endif
1181            regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,LRCKS1_OE, Tristate));
1182            regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,SCLKS1_OE, Tristate));
1183            regVal |= (BCHP_FIELD_ENUM (AUD_FMM_MISC_SEROUT_OE,SDATS1_OE, Tristate));
1184        }
1185    #endif
1186    #if BAPE_CHIP_MAX_I2S_OUTPUTS > 2
1187        #error "Need to support more I2S outputs"
1188    #endif
1189    BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1190
1191    /* Disable the I2S clock and data. */
1192    regAddr = GET_I2S_REG_ADDR3(BCHP_AUD_FMM_OP_CTRL_I2SS, index, _CFG);
1193    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1194    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, CLOCK_ENABLE)|
1195                BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_ENABLE));
1196    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, CLOCK_ENABLE, Disable);
1197    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_ENABLE, Disable);
1198    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1199
1200    return errCode;
1201}
1202
1203/**************************************************************************/
1204
1205static BERR_Code BAPE_I2sOutput_P_ApplySettings_Legacy(
1206    BAPE_I2sOutputHandle handle,
1207    const BAPE_I2sOutputSettings *pSettings,
1208    bool force
1209    )
1210{
1211    uint32_t regAddr, regVal;
1212
1213    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
1214    BDBG_ASSERT(NULL != pSettings);
1215
1216    /* Start by reading the appropriate BCHP_AUD_FMM_OP_CTRL_I2SS<n>_CFG register  for this device. */
1217    regAddr = GET_I2S_REG_ADDR3(BCHP_AUD_FMM_OP_CTRL_I2SS, handle->index, _CFG);
1218    regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1219
1220    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_JUSTIFICATION));
1221    switch ( pSettings->justification )
1222    {
1223    case BAPE_I2sJustification_eMsbFirst:
1224        regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_JUSTIFICATION,MSB);
1225        break;
1226    case BAPE_I2sJustification_eLsbFirst:
1227        regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_JUSTIFICATION,LSB);
1228        break;
1229    default:
1230        BDBG_ERR(("Invalid value for BAPE_I2sOutputSettings.justification: %u", pSettings->justification ));
1231        return BERR_TRACE(BERR_INVALID_PARAMETER);
1232    }
1233
1234    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_ALIGNMENT));
1235    switch ( pSettings->dataAlignment )
1236    {
1237    case BAPE_I2sDataAlignment_eDelayed:
1238        regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_ALIGNMENT, Delayed);
1239        break;
1240    case BAPE_I2sDataAlignment_eAligned:
1241        regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, DATA_ALIGNMENT, Aligned);
1242        break;
1243    default:
1244        BDBG_ERR(("Invalid value for BAPE_I2sOutputSettings.dataAlignment: %u", pSettings->dataAlignment ));
1245        return BERR_TRACE(BERR_INVALID_PARAMETER);
1246    }
1247
1248    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, LRCK_POLARITY));
1249    switch ( pSettings->lrPolarity )
1250    {
1251    case BAPE_I2sLRClockPolarity_eLeftLow:
1252        regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, LRCK_POLARITY, Low_for_left);
1253        break;
1254    case BAPE_I2sLRClockPolarity_eLeftHigh:
1255        regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, LRCK_POLARITY, High_for_left);
1256        break;
1257    default:
1258        BDBG_ERR(("Invalid value for BAPE_I2sOutputSettings.lrPolarity: %u", pSettings->lrPolarity ));
1259        return BERR_TRACE(BERR_INVALID_PARAMETER);
1260    }
1261
1262    /*  Since setting the sclkRate involves updating two registers, only bother with this
1263     *  if somebody is actually changing it.
1264     */
1265    if (pSettings->sclkRate != handle->settings.sclkRate || force)
1266    {
1267        regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, SCLKS_PER_1FS_DIV32));
1268        switch ( pSettings->sclkRate )
1269        {
1270        case BAPE_SclkRate_e64Fs:
1271            regVal |= BCHP_FIELD_DATA(AUD_FMM_OP_CTRL_I2SS0_CFG, SCLKS_PER_1FS_DIV32, 2 );
1272            break;
1273
1274        case BAPE_SclkRate_e128Fs:
1275            regVal |= BCHP_FIELD_DATA(AUD_FMM_OP_CTRL_I2SS0_CFG, SCLKS_PER_1FS_DIV32, 4 );
1276            break;
1277
1278        default:
1279            BDBG_ERR(("Invalid value for BAPE_I2sOutputSettings.sclkRate: %u", pSettings->sclkRate ));
1280            return BERR_TRACE(BERR_INVALID_PARAMETER);
1281        }
1282
1283        /* Set the new sclkRate into the settings struct so that ..._UpdateMclkReg_isr()
1284         * will be able to use it.
1285         */
1286        handle->settings.sclkRate = pSettings->sclkRate;
1287
1288        /* Now update the MCLK_CONFIG register.  */
1289        BKNI_EnterCriticalSection();
1290        BAPE_I2sOutput_P_UpdateMclkReg_isr( handle );
1291        BKNI_LeaveCriticalSection();
1292    }
1293
1294    /* We only support 24 bits per sample. */
1295    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CFG, BITS_PER_SAMPLE ));
1296    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CFG, BITS_PER_SAMPLE, Bitwidth24);
1297
1298    BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1299
1300    if ( pSettings->stereoMode != handle->settings.stereoMode || force )
1301    {
1302        regAddr = GET_I2S_CROSSBAR_ADDR(handle->index);
1303        regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1304        regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_L)|
1305                    BCHP_MASK(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_R));
1306        switch ( pSettings->stereoMode )
1307        {
1308        default:
1309        case BAPE_StereoMode_eLeftRight:
1310            regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_L, In_l);
1311            regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_R, In_r);
1312            break;
1313        case BAPE_StereoMode_eLeftLeft:
1314            regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_L, In_l);
1315            regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_R, In_l);
1316            break;
1317        case BAPE_StereoMode_eRightRight:
1318            regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_L, In_r);
1319            regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_R, In_r);
1320            break;
1321        case BAPE_StereoMode_eRightLeft:
1322            regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_L, In_r);
1323            regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_I2SS0_CROSSBAR, OUT_R, In_l);
1324            break;           
1325        }
1326        BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1327        handle->settings.stereoMode = pSettings->stereoMode;
1328    }
1329
1330    handle->settings = *pSettings;
1331
1332    return BERR_SUCCESS;
1333}
1334
1335static BERR_Code BAPE_I2sOutput_P_Enable_Legacy(BAPE_OutputPort output)
1336{
1337    BAPE_I2sOutputHandle handle;
1338    BAPE_IopStreamSettings streamSettings;
1339    BERR_Code errCode;
1340    unsigned streamId;
1341   
1342    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
1343
1344    handle = output->pHandle;
1345    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
1346
1347    BDBG_ASSERT(false == handle->enabled);
1348
1349    streamId = GET_I2S_IOP_STREAM_ID(handle->index);
1350   
1351    /* Write source FCI to IOP */
1352    BAPE_Iop_P_GetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1353    streamSettings.resolution = 24;
1354    streamSettings.input = output->sourceMixerFci.ids[BAPE_ChannelPair_eLeftRight];         /* Take source FCI provided from mixer */
1355    errCode = BAPE_Iop_P_SetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1356    if ( errCode )
1357    {
1358        return BERR_TRACE(errCode);
1359    }
1360
1361    streamId = GET_I2S_OP_STREAM_ID(handle->index);
1362    BDBG_MSG(("Enabling %s [stream %u]", handle->name, streamId));
1363   
1364    /* Write the enable bit in the OP (only stereo) */
1365    BDBG_MSG(("Writing %x to enable set", (BCHP_MASK(AUD_FMM_OP_CTRL_ENABLE_SET, STREAM0_ENA))<<(streamId)));
1366    BREG_Write32(handle->deviceHandle->regHandle, 
1367                 BCHP_AUD_FMM_OP_CTRL_ENABLE_SET,
1368                 (BCHP_MASK(AUD_FMM_OP_CTRL_ENABLE_SET, STREAM0_ENA))<<(streamId));
1369
1370    handle->enabled = true;
1371    return BERR_SUCCESS;
1372}
1373
1374/**************************************************************************/
1375
1376static void BAPE_I2sOutput_P_Disable_Legacy(BAPE_OutputPort output)
1377{
1378    BAPE_I2sOutputHandle handle;
1379    BAPE_IopStreamSettings streamSettings;
1380    BERR_Code errCode;
1381    unsigned streamId;
1382
1383    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
1384
1385    handle = output->pHandle;
1386    BDBG_OBJECT_ASSERT(handle, BAPE_I2sOutput);
1387
1388    streamId = GET_I2S_OP_STREAM_ID(handle->index);
1389    BDBG_MSG(("Disabling %s [stream %u]", handle->name, streamId));
1390
1391    /* Clear the enable bit in the OP */
1392    BDBG_MSG(("Writing %x to enable clear", (BCHP_MASK(AUD_FMM_OP_CTRL_ENABLE_SET, STREAM0_ENA))<<(streamId)));
1393    BREG_Write32(handle->deviceHandle->regHandle, 
1394                 BCHP_AUD_FMM_OP_CTRL_ENABLE_CLEAR,
1395                 BCHP_MASK(AUD_FMM_OP_CTRL_ENABLE_CLEAR, STREAM0_ENA)<<streamId);
1396
1397    /* Reset source FCI to Invalid */
1398    streamId = GET_I2S_IOP_STREAM_ID(handle->index);   
1399    BAPE_Iop_P_GetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1400    streamSettings.input = BAPE_FCI_ID_INVALID;
1401    errCode = BAPE_Iop_P_SetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1402    BDBG_ASSERT(BERR_SUCCESS == errCode);
1403
1404    handle->enabled = false;
1405}
1406
1407#endif
1408/***************************************************************************
1409Summary:
1410Test code to support I2S testing
1411***************************************************************************/
1412#ifdef  SETUP_PINMUX_FOR_I2S_OUT_ON_7425
1413
1414#include "bchp_aon_pin_ctrl.h"
1415#include "bchp_sun_top_ctrl.h"
1416
1417static void BAPE_I2sOutput_P_SetupPinmuxForI2sTesting( BAPE_Handle deviceHandle )
1418{
1419    uint32_t    reg;
1420
1421    /* First, route the I2S0 outputs to somewhere that we can attach to them.
1422     * It seems that we should be able to send them to either aon_gpio
1423     * pins 01,02,03, or aon_gpio pins 10,11,12.  But it doesn't seem like
1424     * AON_GPIO_03 works.
1425     */
1426    #if 1
1427        reg = BREG_Read32(deviceHandle->regHandle,BCHP_AON_PIN_CTRL_PIN_MUX_CTRL_1);
1428   
1429        reg &=~(    BCHP_MASK(AON_PIN_CTRL_PIN_MUX_CTRL_1, aon_gpio_10 ) |
1430                    BCHP_MASK(AON_PIN_CTRL_PIN_MUX_CTRL_1, aon_gpio_11 ) |
1431                    BCHP_MASK(AON_PIN_CTRL_PIN_MUX_CTRL_1, aon_gpio_12 ) );
1432   
1433        reg |=(    BCHP_FIELD_DATA(AON_PIN_CTRL_PIN_MUX_CTRL_1, aon_gpio_10, 3 ) |  /* I2S_CLK0_OUT  on J2303/14 (Front panel i/f connector) */
1434                   BCHP_FIELD_DATA(AON_PIN_CTRL_PIN_MUX_CTRL_1, aon_gpio_11, 3 ) |  /* I2S_DATA0_OUT on J2303/15 (Front panel i/f connector) */
1435                   BCHP_FIELD_DATA(AON_PIN_CTRL_PIN_MUX_CTRL_1, aon_gpio_12, 3 ) ); /* I2S_LR0_OUT   on J2303/16 (Front panel i/f connector) */
1436   
1437        BREG_Write32 (deviceHandle->regHandle, BCHP_AON_PIN_CTRL_PIN_MUX_CTRL_1, reg);
1438    #else
1439        reg = BREG_Read32(deviceHandle->regHandle,BCHP_AON_PIN_CTRL_PIN_MUX_CTRL_0);
1440   
1441        reg &=~(    BCHP_MASK(AON_PIN_CTRL_PIN_MUX_CTRL_0, aon_gpio_01 ) |
1442                    BCHP_MASK(AON_PIN_CTRL_PIN_MUX_CTRL_0, aon_gpio_02 ) |
1443                    BCHP_MASK(AON_PIN_CTRL_PIN_MUX_CTRL_0, aon_gpio_03 ) );
1444   
1445        reg |=(    BCHP_FIELD_DATA(AON_PIN_CTRL_PIN_MUX_CTRL_0, aon_gpio_01, 3 ) |  /* I2S_CLK0_OUT  on J2303/10 (Front panel i/f connector) */
1446                   BCHP_FIELD_DATA(AON_PIN_CTRL_PIN_MUX_CTRL_0, aon_gpio_02, 3 ) |  /* I2S_DATA0_OUT on J2303/11 (Front panel i/f connector) */
1447                   BCHP_FIELD_DATA(AON_PIN_CTRL_PIN_MUX_CTRL_0, aon_gpio_03, 3 ) ); /* I2S_LR0_OUT   on J2303/12 (Front panel i/f connector) */
1448   
1449        BREG_Write32 (deviceHandle->regHandle, BCHP_AON_PIN_CTRL_PIN_MUX_CTRL_0, reg);
1450    #endif
1451
1452    /* Now, route the I2S1 outputs to somewhere that we can attach to them.
1453     * These can only come out on gpio pins 55,56,57.
1454     */
1455    reg = BREG_Read32(deviceHandle->regHandle,BCHP_SUN_TOP_CTRL_PIN_MUX_CTRL_12);
1456
1457    reg &=~(    BCHP_MASK(SUN_TOP_CTRL_PIN_MUX_CTRL_12, gpio_057 ) |
1458                BCHP_MASK(SUN_TOP_CTRL_PIN_MUX_CTRL_12, gpio_055 ) |
1459                BCHP_MASK(SUN_TOP_CTRL_PIN_MUX_CTRL_12, gpio_056 ) );
1460
1461    reg |=(    BCHP_FIELD_DATA(SUN_TOP_CTRL_PIN_MUX_CTRL_12, gpio_057, 5 ) |  /* I2S_CLK1 on  J2902/3  (RMXP_OUT connector)  */
1462               BCHP_FIELD_DATA(SUN_TOP_CTRL_PIN_MUX_CTRL_12, gpio_055, 5 ) |  /* I2S_DATA1 on J2902/21 (RMXP_OUT connector)  */
1463               BCHP_FIELD_DATA(SUN_TOP_CTRL_PIN_MUX_CTRL_12, gpio_056, 5 ) ); /* I2S_LR1 on   J2902/23 (RMXP_OUT connector)  */
1464
1465    BREG_Write32 (deviceHandle->regHandle, BCHP_SUN_TOP_CTRL_PIN_MUX_CTRL_12, reg);
1466
1467    /* Route each "External MCLK" (also called AUD_FS_CLKx)  */
1468    reg = BREG_Read32(deviceHandle->regHandle,BCHP_AON_PIN_CTRL_PIN_MUX_CTRL_2);
1469    reg &=~ ( BCHP_MASK(AON_PIN_CTRL_PIN_MUX_CTRL_2, gpio_099) |
1470              BCHP_MASK(AON_PIN_CTRL_PIN_MUX_CTRL_2, gpio_100) );
1471    reg |=  ( BCHP_FIELD_DATA(AON_PIN_CTRL_PIN_MUX_CTRL_2, gpio_099, 2 ) |  /* External MCLK0 (AUD_FS_CLK0) on J3002/1 */
1472              BCHP_FIELD_DATA(AON_PIN_CTRL_PIN_MUX_CTRL_2, gpio_100, 2 ) ); /* External MCLK1 (AUD_FS_CLK1) on J3002/5 */
1473    BREG_Write32 (deviceHandle->regHandle, BCHP_AON_PIN_CTRL_PIN_MUX_CTRL_2, reg);
1474}
1475#endif /* SETUP_PINMUX_FOR_I2S_OUT_ON_7425 */
1476
1477
1478/***************************************************************************
1479    Define stub functions for when there are no I2S outputs.
1480***************************************************************************/
1481#else /* BAPE_CHIP_MAX_I2S_OUTPUTS <= 0 */
1482    /* No I2S outputs, just use stubbed out functions. */
1483
1484/**************************************************************************/
1485
1486void BAPE_I2sOutput_GetDefaultSettings(
1487    BAPE_I2sOutputSettings *pSettings
1488    )
1489{
1490    BSTD_UNUSED(pSettings);
1491}
1492
1493/**************************************************************************/
1494
1495BERR_Code BAPE_I2sOutput_Open(
1496    BAPE_Handle deviceHandle,
1497    unsigned index,
1498    const BAPE_I2sOutputSettings *pSettings,
1499    BAPE_I2sOutputHandle *pHandle             /* [out] */
1500    )
1501{
1502    BSTD_UNUSED(deviceHandle);
1503    BSTD_UNUSED(index);
1504    BSTD_UNUSED(pSettings);
1505
1506    *pHandle = NULL;
1507
1508    return BERR_NOT_SUPPORTED;
1509}
1510
1511/**************************************************************************/
1512
1513void BAPE_I2sOutput_Close(
1514    BAPE_I2sOutputHandle handle
1515    )
1516{
1517    BSTD_UNUSED(handle);
1518}
1519
1520/**************************************************************************/
1521
1522void BAPE_I2sOutput_GetSettings(
1523    BAPE_I2sOutputHandle handle,
1524    BAPE_I2sOutputSettings *pSettings     /* [out] */
1525    )
1526{
1527    BSTD_UNUSED(handle);
1528    BSTD_UNUSED(pSettings);
1529}
1530
1531/**************************************************************************/
1532
1533BERR_Code BAPE_I2sOutput_SetSettings(
1534    BAPE_I2sOutputHandle handle,
1535    const BAPE_I2sOutputSettings *pSettings
1536    )
1537{
1538    BSTD_UNUSED(handle);
1539    BSTD_UNUSED(pSettings);
1540
1541    return BERR_NOT_SUPPORTED;
1542}
1543
1544/**************************************************************************/
1545
1546void BAPE_I2sOutput_GetOutputPort(
1547    BAPE_I2sOutputHandle handle,
1548    BAPE_OutputPort *pOutputPort        /* [out] */
1549    )
1550{
1551    BSTD_UNUSED(handle);
1552
1553    *pOutputPort = NULL;
1554}
1555
1556/**************************************************************************/
1557
1558BERR_Code BAPE_I2sOutput_P_ResumeFromStandby(BAPE_Handle bapeHandle)
1559{
1560    BSTD_UNUSED(bapeHandle);
1561    return BERR_SUCCESS;
1562}
1563
1564#endif /* BAPE_CHIP_MAX_I2S_OUTPUTS > */
1565
Note: See TracBrowser for help on using the repository browser.