source: svn/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_spdif_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: 54.7 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2006-2012, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bape_spdif_output.c $
11 * $brcm_Revision: Hydra_Software_Devel/18 $
12 * $brcm_Date: 3/6/12 3:04p $
13 *
14 * Module Description: Audio Decoder Interface
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/ape/7422/bape_spdif_output.c $
19 *
20 * Hydra_Software_Devel/18   3/6/12 3:04p gskerl
21 * SW7425-2570: Renamed OutputPortObject substruct from connector to
22 * outputPort.
23 *
24 * Hydra_Software_Devel/17   2/21/12 6:40p jgarrett
25 * SW7231-363: Failing gracefully if AC3+ passthrough is requested on
26 * SPDIF
27 *
28 * Hydra_Software_Devel/16   11/14/11 3:36p gskerl
29 * SW7429-18: Merging 7429 changes back to main branch.
30 *
31 * Hydra_Software_Devel/SW7429-18/2   11/1/11 4:32p jgarrett
32 * SW7429-18: Adding SPDIF output support for 7429
33 *
34 * Hydra_Software_Devel/SW7429-18/1   10/21/11 6:29p jgarrett
35 * SW7429-18: Initial compileable version for 7429
36 *
37 * Hydra_Software_Devel/15   10/5/11 6:10p gskerl
38 * SW7231-129: Added support for recovering hardware state after power
39 * standby/resume.
40 *
41 * Hydra_Software_Devel/14   9/13/11 11:06a jgarrett
42 * SW7346-436: Re-applying channel status bit state on each enable call
43 *
44 * Hydra_Software_Devel/13   7/8/11 4:25p gskerl
45 * SW7552-72: Added support for NCO/Mclkgen audio clock sources
46 *
47 * Hydra_Software_Devel/12   5/20/11 5:16p jgarrett
48 * SW7425-402: Adding error code to handle output enable callback failing.
49 *
50 * Hydra_Software_Devel/11   5/3/11 10:48a gskerl
51 * SW7422-354: Added index and type args to APE_P_InitOutputPort macro
52 *
53 * Hydra_Software_Devel/10   4/16/11 12:16p jgarrett
54 * SW7425-371: Removing tab characters
55 *
56 * Hydra_Software_Devel/9   4/6/11 1:23a jgarrett
57 * SW35330-35: Merge to main branch
58 *
59 * Hydra_Software_Devel/SW35330-35/1   4/5/11 12:50p jgarrett
60 * SW35330-35: FMM Abstraction refactoring to support DTV
61 *
62 * Hydra_Software_Devel/8   3/28/11 5:55p srajapur
63 * SW7422-146: [7425] Fixing dither.
64 *
65 * Hydra_Software_Devel/7   3/22/11 3:01p gskerl
66 * SW7422-146: Changed audio output connector callbacks to take the output
67 * connector as an argument
68 *
69 * Hydra_Software_Devel/6   2/22/11 5:43p jgarrett
70 * SW7422-146: Implemented type renaming based on filter graph review
71 * comments
72 *
73 * Hydra_Software_Devel/5   2/17/11 5:29p gskerl
74 * SW7422-146: Added comment headers at the beginning of each function.
75 * Some other minor cosmetic changes.
76 *
77 * Hydra_Software_Devel/4   2/16/11 4:51p jgarrett
78 * SW7422-146: Coverity CID 250
79 *
80 * Hydra_Software_Devel/3   2/11/11 7:38p gskerl
81 * SW7422-146: Fixed compiler warning about pllclksel being used
82 * uninitialized.
83 *
84 * Hydra_Software_Devel/2   2/10/11 5:45p gskerl
85 * SW7422-146: Changed calling sequence for the audio output setMclk_isr
86 * callbacks
87 *
88 * Hydra_Software_Devel/1   12/16/10 4:05p jgarrett
89 * SW7422-146: Initial compilable APE for 7422
90 *
91 ***************************************************************************/
92
93#include "bape.h"
94#include "bape_priv.h"
95
96BDBG_MODULE(bape_spdif_output);
97
98#if BAPE_CHIP_MAX_SPDIF_OUTPUTS > 0
99
100BDBG_OBJECT_ID(BAPE_SpdifOutput);
101
102typedef struct BAPE_SpdifOutput
103{
104    BDBG_OBJECT(BAPE_SpdifOutput)
105    BAPE_Handle deviceHandle;
106    BAPE_SpdifOutputSettings settings;
107    unsigned index;
108    BAPE_OutputPortObject outputPort;
109    uint32_t offset;
110    unsigned sampleRate;
111    struct
112    {
113        BAPE_MclkSource mclkSource;
114        unsigned pllChannel;    /* only applies if mclkSource refers to a PLL */
115        unsigned mclkFreqToFsRatio;
116    } mclkInfo;
117    bool enabled;
118    char name[9];   /* SPDIF %d */
119} BAPE_SpdifOutput;
120
121/* Static function prototypes */
122static void      BAPE_SpdifOutput_P_SetCbits_isr(BAPE_SpdifOutputHandle handle);
123static BERR_Code BAPE_SpdifOutput_P_OpenHw(BAPE_SpdifOutputHandle handle);
124static BERR_Code BAPE_SpdifOutput_P_CloseHw(BAPE_SpdifOutputHandle handle);
125static BERR_Code BAPE_SpdifOutput_P_ApplySettings(BAPE_SpdifOutputHandle handle, 
126                                                  const BAPE_SpdifOutputSettings *pSettings, bool force );
127
128/* Output port callbacks */
129static void      BAPE_SpdifOutput_P_SetTimingParams_isr(BAPE_OutputPort output, unsigned sampleRate, BAVC_Timebase timebase);
130static void      BAPE_SpdifOutput_P_SetMute(BAPE_OutputPort output, bool muted, bool sync);
131static BERR_Code BAPE_SpdifOutput_P_Enable(BAPE_OutputPort output);
132static void      BAPE_SpdifOutput_P_Disable(BAPE_OutputPort output);
133static void      BAPE_SpdifOutput_P_SetMclk_isr(BAPE_OutputPort output, BAPE_MclkSource mclkSource, unsigned pllChannel, unsigned mclkFreqToFsRatio);
134
135#if BAPE_CHIP_MAX_SPDIF_OUTPUTS  > 1
136    #define  GET_SPDIF_REG_ADDR2(prefix,idx)         (prefix##0         + (prefix##1         - prefix##0        ) * idx )
137    #define  GET_SPDIF_REG_ADDR3(prefix,idx,suffix)  (prefix##0##suffix + (prefix##1##suffix - prefix##0##suffix) * idx )
138    #define  GET_SPDIF_STREAM_ID(idx) ((idx == 1)?0:(BDBG_ASSERT(0),0))
139#else
140    #define  GET_SPDIF_REG_ADDR2(prefix,idx       )  (prefix##0         )
141    #define  GET_SPDIF_REG_ADDR3(prefix,idx,suffix)  (prefix##0##suffix )
142    #define  GET_SPDIF_STREAM_ID(idx) (0)
143#endif
144
145/* Implementations for Legacy vs. New [7429] Hardware */
146#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
147#include "bchp_aud_fmm_iop_out_spdif_0.h"
148static void      BAPE_SpdifOutput_P_SetCbits_IopOut_isr(BAPE_SpdifOutputHandle handle);
149static void      BAPE_SpdifOutput_P_SetMute_IopOut(BAPE_OutputPort output, bool muted, bool sync);
150static BERR_Code BAPE_SpdifOutput_P_Enable_IopOut(BAPE_OutputPort output);
151static void      BAPE_SpdifOutput_P_Disable_IopOut(BAPE_OutputPort output);
152static void      BAPE_SpdifOutput_P_SetMclk_IopOut_isr(BAPE_OutputPort output, BAPE_MclkSource mclkSource, unsigned pllChannel, unsigned mclkFreqToFsRatio);
153static BERR_Code BAPE_SpdifOutput_P_OpenHw_IopOut(BAPE_SpdifOutputHandle handle);
154static BERR_Code BAPE_SpdifOutput_P_CloseHw_IopOut(BAPE_SpdifOutputHandle handle);
155static BERR_Code BAPE_SpdifOutput_P_ApplySettings_IopOut(BAPE_SpdifOutputHandle handle, 
156                                                         const BAPE_SpdifOutputSettings *pSettings, bool force);
157#else
158static void      BAPE_SpdifOutput_P_SetCbits_Legacy_isr(BAPE_SpdifOutputHandle handle);
159static void      BAPE_SpdifOutput_P_SetMute_Legacy(BAPE_OutputPort output, bool muted, bool sync);
160static BERR_Code BAPE_SpdifOutput_P_Enable_Legacy(BAPE_OutputPort output);
161static void      BAPE_SpdifOutput_P_Disable_Legacy(BAPE_OutputPort output);
162static void      BAPE_SpdifOutput_P_SetMclk_Legacy_isr(BAPE_OutputPort output, BAPE_MclkSource mclkSource, unsigned pllChannel, unsigned mclkFreqToFsRatio);
163static BERR_Code BAPE_SpdifOutput_P_OpenHw_Legacy(BAPE_SpdifOutputHandle handle);
164static BERR_Code BAPE_SpdifOutput_P_CloseHw_Legacy(BAPE_SpdifOutputHandle handle);
165static BERR_Code BAPE_SpdifOutput_P_ApplySettings_Legacy(BAPE_SpdifOutputHandle handle, 
166                                                         const BAPE_SpdifOutputSettings *pSettings, bool force);
167#endif
168
169/***************************************************************************
170        Public APIs: From bape_output.h
171***************************************************************************/
172void BAPE_SpdifOutput_GetDefaultSettings(
173    BAPE_SpdifOutputSettings *pSettings
174    )
175{
176    BDBG_ASSERT(NULL != pSettings);
177    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
178
179    pSettings->stereoMode = BAPE_StereoMode_eLeftRight;
180    pSettings->ditherEnabled = true;
181    pSettings->limitTo16Bits = false;
182    pSettings->underflowBurst = BAPE_SpdifBurstType_ePause;
183    pSettings->useRawChannelStatus = false;
184    /* channel status is initialized to zero for all fields */
185}
186
187/**************************************************************************/
188
189BERR_Code BAPE_SpdifOutput_Open(
190    BAPE_Handle deviceHandle,
191    unsigned index,
192    const BAPE_SpdifOutputSettings *pSettings,
193    BAPE_SpdifOutputHandle *pHandle             /* [out] */
194    )
195{
196    BERR_Code errCode;
197    BAPE_SpdifOutputHandle handle;
198    BAPE_SpdifOutputSettings defaultSettings;
199
200    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
201    BDBG_ASSERT(NULL != pHandle);
202   
203    BDBG_MSG(("%s: Opening SPDIF Output: %u", __FUNCTION__, index));
204
205    *pHandle = NULL;
206
207    if ( index >= BAPE_CHIP_MAX_SPDIF_OUTPUTS )
208    {
209        BDBG_ERR(("Request to open SPDIF output %d but chip only has %u SPDIF outputs", index, BAPE_CHIP_MAX_SPDIF_OUTPUTS));
210        return BERR_TRACE(BERR_INVALID_PARAMETER);
211    }
212
213    if ( deviceHandle->spdifOutputs[index] )
214    {
215        BDBG_ERR(("SPDIF output %d already open", index));
216        return BERR_TRACE(BERR_INVALID_PARAMETER);
217    }
218
219    /* Allocate the device structure, then fill in all the fields. */
220    handle = BKNI_Malloc(sizeof(BAPE_SpdifOutput));
221    if ( NULL == handle )
222    {
223        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
224    }
225
226    BKNI_Memset(handle, 0, sizeof(BAPE_SpdifOutput));
227    BDBG_OBJECT_SET(handle, BAPE_SpdifOutput);
228    handle->deviceHandle = deviceHandle;
229    handle->index = index;
230    BAPE_P_InitOutputPort(&handle->outputPort, BAPE_OutputPortType_eSpdifOutput, index, handle);
231    handle->outputPort.maxChannelPairs = 1;  /* SpdifOutput is stero or compressed only */
232    handle->outputPort.compressedSupported = true;
233    handle->outputPort.pllRequired = true;
234    handle->outputPort.setTimingParams_isr = BAPE_SpdifOutput_P_SetTimingParams_isr;
235    handle->outputPort.setMute = BAPE_SpdifOutput_P_SetMute;
236    handle->outputPort.enable = BAPE_SpdifOutput_P_Enable;
237    handle->outputPort.disable = BAPE_SpdifOutput_P_Disable;
238    handle->outputPort.setMclk_isr = BAPE_SpdifOutput_P_SetMclk_isr;
239    BKNI_Snprintf(handle->name, sizeof(handle->name), "SPDIF %u", index);
240    handle->outputPort.pName = handle->name;
241
242    /* Currently we only support one SPDIF, this can be expanded later if we support more */
243    #if BAPE_CHIP_MAX_SPDIF_OUTPUTS > 1
244        #error "Need to support more SPDIF outputs"
245    #endif
246    handle->offset = 0;
247
248    /* Setup to 48k, muted by default */
249    BKNI_EnterCriticalSection();
250    BAPE_SpdifOutput_P_SetTimingParams_isr(&handle->outputPort, 48000, BAVC_Timebase_e0);
251    BKNI_LeaveCriticalSection();
252
253    /* Init to specified settings */
254    if ( NULL == pSettings )
255    {
256        BAPE_SpdifOutput_GetDefaultSettings(&defaultSettings);
257        pSettings = &defaultSettings;
258    }
259
260    errCode = BAPE_SpdifOutput_P_OpenHw(handle);
261    if ( errCode )
262    {
263        BAPE_SpdifOutput_Close(handle);
264        return BERR_TRACE(errCode);
265    }
266
267    /* mute */
268    BAPE_SpdifOutput_P_SetMute(&handle->outputPort, true, false);
269
270    /* Initialize hardware before applying settings */
271    BKNI_EnterCriticalSection();
272    BAPE_SpdifOutput_P_SetMclk_isr(&handle->outputPort, BAPE_MclkSource_ePll0, 0, BAPE_BASE_PLL_TO_FS_RATIO);
273    BKNI_LeaveCriticalSection();   
274
275    errCode = BAPE_SpdifOutput_P_ApplySettings(handle, pSettings, true);   /* true => force update of HW */
276    if ( errCode )
277    {
278        BAPE_SpdifOutput_Close(handle);
279        return BERR_TRACE(errCode);
280    }
281
282    *pHandle = handle;
283    handle->deviceHandle->spdifOutputs[index] = handle;
284    return BERR_SUCCESS;
285}
286
287/**************************************************************************/
288
289void BAPE_SpdifOutput_Close(
290    BAPE_SpdifOutputHandle handle
291    )
292{
293    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
294
295    /* Make sure we're not still connected to anything */
296    if ( handle->outputPort.mixer )
297    {
298        BDBG_ERR(("Cannot close SPDIF output %p (%d), still connected to mixer %p", handle, handle->index, handle->outputPort.mixer));
299        BDBG_ASSERT(NULL == handle->outputPort.mixer);
300        return;
301    }
302
303    BAPE_SpdifOutput_P_CloseHw(handle);
304
305    BDBG_ASSERT(handle->index < BAPE_CHIP_MAX_SPDIF_OUTPUTS);
306    handle->deviceHandle->spdifOutputs[handle->index] = NULL;
307    BDBG_OBJECT_DESTROY(handle, BAPE_SpdifOutput);
308    BKNI_Free(handle);   
309}
310
311/**************************************************************************/
312
313void BAPE_SpdifOutput_GetSettings(
314    BAPE_SpdifOutputHandle handle,
315    BAPE_SpdifOutputSettings *pSettings     /* [out] */
316    )
317{
318    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
319    BDBG_ASSERT(NULL != pSettings);
320    *pSettings = handle->settings;
321}
322
323/**************************************************************************/
324
325BERR_Code BAPE_SpdifOutput_SetSettings(
326    BAPE_SpdifOutputHandle handle,
327    const BAPE_SpdifOutputSettings *pSettings
328    )
329{
330    BERR_Code   errCode = BERR_SUCCESS;
331
332    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
333    BDBG_ASSERT(NULL != pSettings);
334
335    errCode = BAPE_SpdifOutput_P_ApplySettings(handle, pSettings, false); /* false => don't force (only update HW for changes) */
336    return errCode;
337}
338
339/**************************************************************************/
340
341void BAPE_SpdifOutput_GetOutputPort(
342    BAPE_SpdifOutputHandle handle,
343    BAPE_OutputPort *pOutputPort        /* [out] */
344    )
345{
346    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
347    BDBG_ASSERT(NULL != pOutputPort);
348    *pOutputPort = &handle->outputPort;
349}
350
351/***************************************************************************
352        BAPE Internal APIs: From bape_fmm_priv.h
353***************************************************************************/
354
355BERR_Code BAPE_SpdifOutput_P_ResumeFromStandby(BAPE_Handle bapeHandle)
356{
357    BERR_Code   errCode = BERR_SUCCESS;
358    unsigned    spdifOutputIndex;
359
360    BDBG_OBJECT_ASSERT(bapeHandle, BAPE_Device);
361
362    /* For each opened SpdifOutput, call the functions necessary to restore the hardware to it's appropriate state. */
363    for ( spdifOutputIndex=0 ; spdifOutputIndex<BAPE_CHIP_MAX_SPDIF_OUTPUTS ; spdifOutputIndex++ )
364    {
365        if ( bapeHandle->spdifOutputs[spdifOutputIndex] )       /* If this SpdifOutput is open... */
366        {
367            BAPE_SpdifOutputHandle hSpdifOutput = bapeHandle->spdifOutputs[spdifOutputIndex];
368
369            /* Put the HW into the generic open state. */
370            errCode = BAPE_SpdifOutput_P_OpenHw(hSpdifOutput);
371            if ( errCode ) return BERR_TRACE(errCode);
372           
373            /* Now apply changes for the settings struct. */
374            errCode = BAPE_SpdifOutput_P_ApplySettings(hSpdifOutput, &hSpdifOutput->settings, true);   /* true => force update of HW */
375            if ( errCode ) return BERR_TRACE(errCode);
376
377            /* Now restore the dynamic stuff from the values saved in the device struct. */
378            BKNI_EnterCriticalSection();
379
380                BAPE_SpdifOutput_P_SetTimingParams_isr(&hSpdifOutput->outputPort, 
381                                                     hSpdifOutput->sampleRate, 
382                                                     0);    /* timebase is unused, 0 is dummy value */
383                BAPE_SpdifOutput_P_SetMclk_isr(&hSpdifOutput->outputPort,
384                                             hSpdifOutput->mclkInfo.mclkSource,
385                                             hSpdifOutput->mclkInfo.pllChannel,
386                                             hSpdifOutput->mclkInfo.mclkFreqToFsRatio );
387            BKNI_LeaveCriticalSection();
388
389        }
390    }
391    return errCode;
392}
393
394/***************************************************************************
395        Private callbacks: Protyped above
396***************************************************************************/
397
398static void BAPE_SpdifOutput_P_SetTimingParams_isr(BAPE_OutputPort output, unsigned sampleRate, BAVC_Timebase timebase)
399{
400    BAPE_SpdifOutputHandle handle;
401
402    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
403
404    handle = output->pHandle;
405    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
406
407    BSTD_UNUSED(timebase);  /* SPDIF doesn't care */
408
409    handle->sampleRate = sampleRate;
410
411    BAPE_SpdifOutput_P_SetCbits_isr(handle);
412}
413
414/**************************************************************************/
415
416static void BAPE_SpdifOutput_P_SetMute(BAPE_OutputPort output, bool muted, bool sync)
417{
418#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
419    BAPE_SpdifOutput_P_SetMute_IopOut(output, muted, sync);
420#else
421    BAPE_SpdifOutput_P_SetMute_Legacy(output, muted, sync);
422#endif
423}
424
425/**************************************************************************/
426
427static BERR_Code BAPE_SpdifOutput_P_Enable(BAPE_OutputPort output)
428{
429#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
430    return BAPE_SpdifOutput_P_Enable_IopOut(output);
431#else
432    return BAPE_SpdifOutput_P_Enable_Legacy(output);
433#endif
434}
435
436/**************************************************************************/
437
438static void BAPE_SpdifOutput_P_Disable(BAPE_OutputPort output)
439{
440#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
441    BAPE_SpdifOutput_P_Disable_IopOut(output);
442#else
443    BAPE_SpdifOutput_P_Disable_Legacy(output);
444#endif
445}
446
447/**************************************************************************/
448
449static void BAPE_SpdifOutput_P_SetMclk_isr(BAPE_OutputPort output, BAPE_MclkSource mclkSource, unsigned pllChannel, unsigned mclkFreqToFsRatio)
450{
451#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
452    BAPE_SpdifOutput_P_SetMclk_IopOut_isr(output, mclkSource, pllChannel, mclkFreqToFsRatio);
453#else
454    BAPE_SpdifOutput_P_SetMclk_Legacy_isr(output, mclkSource, pllChannel, mclkFreqToFsRatio);
455#endif
456}
457
458/***************************************************************************
459        Private functions: Protyped above
460***************************************************************************/
461
462static void BAPE_SpdifOutput_P_SetCbits_isr(BAPE_SpdifOutputHandle handle)
463{
464#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
465    BAPE_SpdifOutput_P_SetCbits_IopOut_isr(handle);
466#else
467    BAPE_SpdifOutput_P_SetCbits_Legacy_isr(handle);
468#endif
469}
470
471/**************************************************************************/
472
473static BERR_Code BAPE_SpdifOutput_P_OpenHw(BAPE_SpdifOutputHandle handle)
474{
475#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
476    return BAPE_SpdifOutput_P_OpenHw_IopOut(handle);
477#else
478    return BAPE_SpdifOutput_P_OpenHw_Legacy(handle);
479#endif
480}
481
482/**************************************************************************/
483
484static BERR_Code BAPE_SpdifOutput_P_CloseHw(BAPE_SpdifOutputHandle handle)
485{
486#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
487    return BAPE_SpdifOutput_P_CloseHw_IopOut(handle);
488#else
489    return BAPE_SpdifOutput_P_CloseHw_Legacy(handle);
490#endif
491}
492
493/**************************************************************************/
494
495static BERR_Code BAPE_SpdifOutput_P_ApplySettings(
496    BAPE_SpdifOutputHandle handle,
497    const BAPE_SpdifOutputSettings *pSettings,
498    bool force
499    )
500{
501#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
502    return BAPE_SpdifOutput_P_ApplySettings_IopOut(handle, pSettings, force);
503#else
504    return BAPE_SpdifOutput_P_ApplySettings_Legacy(handle, pSettings, force);
505#endif
506}
507
508#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_REG_START
509/**************************************************************************
5107429-style RDB
511**************************************************************************/
512static void BAPE_SpdifOutput_P_SetMute_IopOut(BAPE_OutputPort output, bool muted, bool sync)
513{
514    BAPE_SpdifOutputHandle handle;
515
516    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
517
518    handle = output->pHandle;
519    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
520
521    /* Only support one now */
522    BDBG_ASSERT(handle->offset == 0);
523
524    /* Must manipulate CSTAT registers in critical section */
525    BKNI_EnterCriticalSection();
526
527    if ( muted )
528    {
529        BAPE_Reg_P_UpdateEnum_isr(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, OVERWRITE_DATA, Enable);
530    }
531    else
532    {
533        BAPE_Reg_P_UpdateEnum_isr(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, OVERWRITE_DATA, Disable);
534    }
535
536    BKNI_LeaveCriticalSection();
537
538    BSTD_UNUSED(sync);
539}
540
541/**************************************************************************/
542
543static BERR_Code BAPE_SpdifOutput_P_Enable_IopOut(BAPE_OutputPort output)
544{
545    BAPE_Reg_P_FieldList regFieldList;
546    BAPE_SpdifOutputHandle handle;
547    BAPE_MixerHandle mixer;
548
549    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
550
551    handle = output->pHandle;
552    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
553    BDBG_ASSERT(false == handle->enabled);
554    BDBG_ASSERT(NULL != output->mixer);
555
556    mixer = output->mixer;
557
558    BDBG_MSG(("Enabling %s", handle->name));
559
560    BDBG_ASSERT(mixer->numChannelPairs <= 1);
561
562    BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
563    BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, GROUP_ID, 0);
564    BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, CHANNEL_GROUPING, 1);
565    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, STREAM_BIT_RESOLUTION, Res_24_Bit); 
566    BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, FCI_ID, output->sourceMixerFci.ids[0]);
567    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0);       
568
569    /* Update CBITS */
570    BKNI_EnterCriticalSection();
571    BAPE_SpdifOutput_P_SetCbits_isr(handle);
572    BKNI_LeaveCriticalSection();
573
574    /* Enable the interface. */
575    BAPE_Reg_P_UpdateField(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, ENA, 1);
576
577    handle->enabled = true;
578    return BERR_SUCCESS;
579}
580
581/**************************************************************************/
582
583static void BAPE_SpdifOutput_P_Disable_IopOut(BAPE_OutputPort output)
584{
585    BAPE_SpdifOutputHandle handle;
586
587    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
588
589    handle = output->pHandle;
590    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
591
592    BDBG_ASSERT(true == handle->enabled);
593
594    /* Disable the interface */
595    BAPE_Reg_P_UpdateField(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, ENA, 0);
596
597    /* Reset source FCI to Invalid */
598    BAPE_Reg_P_UpdateField(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, AUD_FMM_IOP_OUT_SPDIF_0_STREAM_CFG_0, FCI_ID, BAPE_FCI_ID_INVALID);
599
600    handle->enabled = false;
601}
602
603/**************************************************************************/
604
605static void BAPE_SpdifOutput_P_SetMclk_IopOut_isr(BAPE_OutputPort output, BAPE_MclkSource mclkSource, unsigned pllChannel, unsigned mclkFreqToFsRatio)
606{
607    BAPE_Reg_P_FieldList regFieldList;
608
609    BAPE_SpdifOutputHandle handle;
610
611    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
612
613    handle = output->pHandle;
614    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
615    BDBG_ASSERT(handle->offset == 0);
616
617    /* Save the settings in case we need to re-apply them later. */
618    handle->mclkInfo.mclkSource         = mclkSource;
619    handle->mclkInfo.pllChannel         = pllChannel;
620    handle->mclkInfo.mclkFreqToFsRatio  = mclkFreqToFsRatio;
621
622    BAPE_Reg_P_InitFieldList(handle->deviceHandle, &regFieldList);
623
624    switch ( mclkSource )
625    {
626#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0_PLLCLKSEL_PLL0_ch1
627    case BAPE_MclkSource_ePll0:
628        switch ( pllChannel )
629        {
630        case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL0_ch1); break;
631        case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL0_ch2); break;
632        case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL0_ch3); break;               
633        default: (void) BERR_TRACE(BERR_NOT_SUPPORTED); break;
634        }
635        break;
636#endif
637#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0_PLLCLKSEL_PLL1_ch1
638    case BAPE_MclkSource_ePll1:
639        switch ( pllChannel )
640        {
641        case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL1_ch1); break;
642        case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL1_ch2); break;
643        case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL1_ch3); break;               
644        default: (void) BERR_TRACE(BERR_NOT_SUPPORTED); break;
645        }
646        break;
647#endif
648#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0_PLLCLKSEL_PLL2_ch1
649    case BAPE_MclkSource_ePll2:
650        switch ( pllChannel )
651        {
652        case 0: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL2_ch1); break;
653        case 1: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL2_ch2); break;
654        case 2: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, PLL2_ch3); break;               
655        default: (void) BERR_TRACE(BERR_NOT_SUPPORTED); break;
656        }
657        break;
658#endif
659#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0_PLLCLKSEL_Mclk_gen0
660    case BAPE_MclkSource_eNco0:
661        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, Mclk_gen0); 
662        break;
663#endif
664#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0_PLLCLKSEL_Mclk_gen1
665    case BAPE_MclkSource_eNco1:
666        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, Mclk_gen1); 
667        break;
668#endif
669#ifdef BCHP_AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0_PLLCLKSEL_Mclk_gen2
670    case BAPE_MclkSource_eNco2:
671        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, PLLCLKSEL, Mclk_gen2); 
672        break;
673#endif
674    default:
675        BDBG_ERR(("Unsupported clock source %u for SPDIF %u", mclkSource, handle->index));
676        (void)BERR_TRACE(BERR_NOT_SUPPORTED);
677    }
678
679    switch ( mclkFreqToFsRatio )
680    {
681    case 128: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, MCLK_RATE, MCLK_128fs_SCLK_64fs); break;
682    case 256: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, MCLK_RATE, MCLK_256fs_SCLK_64fs); break;
683    case 384: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, MCLK_RATE, MCLK_384fs_SCLK_64fs); break;
684    case 512: BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0, MCLK_RATE, MCLK_512fs_SCLK_64fs); break;
685    default:
686        BDBG_ERR(("Unsupported MCLK Rate of %uFs", mclkFreqToFsRatio));
687        (void)BERR_TRACE(BERR_NOT_SUPPORTED);
688        break;
689    }
690    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_MCLK_CFG_0);
691}
692
693/***************************************************************************
694        Private functions: Protyped above
695***************************************************************************/
696
697static void BAPE_SpdifOutput_P_SetCbits_IopOut_isr(BAPE_SpdifOutputHandle handle)
698{
699    BAPE_Reg_P_FieldList regFieldList;
700    uint32_t regAddr, regVal;
701    bool compressed;
702    unsigned validity;
703
704    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
705
706    compressed = (handle->outputPort.mixer && handle->outputPort.mixer->compressed)?true:false;
707
708    BDBG_MSG(("Set SPDIF CBITS SR %u", handle->sampleRate));
709
710    /* Only set validity if we're outputting compressed in a non-high-bitrate mode. */
711    if ( compressed && handle->sampleRate != 192000 && handle->sampleRate != 176400 )
712    {
713        validity = 1;
714    }
715    else
716    {
717        validity = 0;
718    }
719
720    /* Tell the HW to hold the current CBITS and set dither correctly */
721    regAddr = BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL;
722    BAPE_Reg_P_InitFieldList_isr(handle->deviceHandle, &regFieldList);
723    if ( handle->settings.ditherEnabled && !compressed )
724    {
725        BAPE_Reg_P_AddEnumToFieldList_isr(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, DITHER_ENA, Enable);
726    }
727    else
728    {
729        BAPE_Reg_P_AddEnumToFieldList_isr(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, DITHER_ENA, Disable);
730    }
731    BAPE_Reg_P_AddToFieldList_isr(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, VALIDITY, validity);
732    BAPE_Reg_P_AddEnumToFieldList_isr(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, HOLD_CSTAT, Hold);
733    BAPE_Reg_P_ApplyFieldList_isr(&regFieldList, regAddr);
734
735    /* Program channel status */
736    if ( handle->settings.useRawChannelStatus )
737    {
738        regVal = 
739            (uint32_t)handle->settings.rawChannelStatus[0] |
740            (((uint32_t)handle->settings.rawChannelStatus[1])<<8) |
741            (((uint32_t)handle->settings.rawChannelStatus[2])<<16) |
742            (((uint32_t)handle->settings.rawChannelStatus[3])<<24);
743        BAPE_Reg_P_Write_isr(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CHANSTAT_0, regVal);
744        regVal = (uint32_t)handle->settings.rawChannelStatus[4];
745        BAPE_Reg_P_Write_isr(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CHANSTAT_1, regVal);
746    }
747    else 
748    {
749        BAPE_Spdif_P_ChannelStatusBits cbits;
750
751        BAPE_P_MapSpdifChannelStatusToBits_isr(&handle->outputPort, &handle->settings.channelStatus, &cbits);
752        BAPE_Reg_P_Write_isr(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CHANSTAT_0, cbits.bits[0]);
753        BAPE_Reg_P_Write_isr(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CHANSTAT_1, cbits.bits[1]);
754    }
755
756    /* Reload the new channel status in HW */
757    BAPE_Reg_P_UpdateEnum_isr(handle->deviceHandle, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_CTRL, HOLD_CSTAT, Update);
758
759    return;
760}
761
762/**************************************************************************/
763
764static BERR_Code BAPE_SpdifOutput_P_OpenHw_IopOut(BAPE_SpdifOutputHandle handle)
765{
766    BERR_Code            errCode = BERR_SUCCESS;
767    BAPE_Handle          deviceHandle;
768    BAPE_Reg_P_FieldList regFieldList;
769
770    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
771
772    deviceHandle = handle->deviceHandle;
773    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
774
775    /* Enable the clock and data while opening the output. */
776
777    BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);
778
779    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, CLOCK_ENABLE, Enable);
780    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, DATA_ENABLE, Enable);
781
782    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG);
783
784    return errCode;
785}
786
787/**************************************************************************/
788
789static BERR_Code BAPE_SpdifOutput_P_CloseHw_IopOut(BAPE_SpdifOutputHandle handle)
790{
791    BERR_Code            errCode = BERR_SUCCESS;
792    BAPE_Handle          deviceHandle;
793    BAPE_Reg_P_FieldList regFieldList;
794
795    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
796
797    deviceHandle = handle->deviceHandle;
798    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
799
800    /* Enable the clock and data while opening the output. */
801
802    BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);
803
804    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, CLOCK_ENABLE, Disable);
805    BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, DATA_ENABLE, Disable);
806
807    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG);
808
809    return errCode;
810}
811
812static BERR_Code BAPE_SpdifOutput_P_ApplySettings_IopOut(
813    BAPE_SpdifOutputHandle handle,
814    const BAPE_SpdifOutputSettings *pSettings,
815    bool force
816    )
817{
818    BAPE_Reg_P_FieldList regFieldList;
819    BAPE_Handle          deviceHandle;
820
821    BSTD_UNUSED(force); /* Not used because HW gets updated unconditionally */
822
823    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
824    BDBG_ASSERT(NULL != pSettings);
825   
826    deviceHandle = handle->deviceHandle;
827    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
828
829    BAPE_Reg_P_InitFieldList(deviceHandle, &regFieldList);
830
831    BAPE_Reg_P_AddToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, LIMIT_TO_16_BITS, (pSettings->limitTo16Bits) ? 1 : 0);
832
833    switch ( pSettings->stereoMode )
834    {
835    default:
836    case BAPE_StereoMode_eLeftRight:
837        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, LR_SELECT, Normal);
838        break;
839    case BAPE_StereoMode_eLeftLeft:
840        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, LR_SELECT, Both_Get_Left);
841        break;
842    case BAPE_StereoMode_eRightRight:
843        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, LR_SELECT, Both_Get_Right);
844        break;
845    case BAPE_StereoMode_eRightLeft:
846        BAPE_Reg_P_AddEnumToFieldList(&regFieldList, AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG, LR_SELECT, Swap);
847        break;       
848    }
849
850    BAPE_Reg_P_ApplyFieldList(&regFieldList, BCHP_AUD_FMM_IOP_OUT_SPDIF_0_SPDIF_FORMAT_CFG);
851
852    handle->settings = *pSettings;
853
854    /* Remaining fields are handled by MS regs.  Must modify those in critical section. */   
855    BKNI_EnterCriticalSection();
856    BAPE_SpdifOutput_P_SetCbits_isr(handle);
857    BKNI_LeaveCriticalSection();
858
859    return BERR_SUCCESS;
860}
861#else
862/**************************************************************************
863Legacy HW routines
864**************************************************************************/
865
866static void BAPE_SpdifOutput_P_SetMute_Legacy(BAPE_OutputPort output, bool muted, bool sync)
867{
868    BAPE_SpdifOutputHandle handle;
869    uint32_t regVal;
870
871    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
872
873    handle = output->pHandle;
874    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
875
876    /* Only support one now */
877    BDBG_ASSERT(handle->offset == 0);
878
879    /* Must manipulate MS registers in critical section */
880    BKNI_EnterCriticalSection();
881    regVal = BREG_Read32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0);
882
883    /* We always use FW channel status, so set override only to mute */
884    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, OVERWRITE_DATA);
885    if ( muted )
886    {
887        regVal |= BCHP_FIELD_ENUM(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, OVERWRITE_DATA, Enable);
888    }
889    else
890    {
891        regVal |= BCHP_FIELD_ENUM(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, OVERWRITE_DATA, Disable);
892    }
893    BREG_Write32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, regVal);
894
895    BKNI_LeaveCriticalSection();
896
897    BSTD_UNUSED(sync);
898}
899
900/**************************************************************************/
901
902static BERR_Code BAPE_SpdifOutput_P_Enable_Legacy(BAPE_OutputPort output)
903{
904    BAPE_SpdifOutputHandle handle;
905    uint32_t regVal;
906    BAPE_IopStreamSettings streamSettings;
907    BERR_Code errCode;
908    unsigned streamId;
909
910   
911    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
912
913    handle = output->pHandle;
914    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
915
916    if ( output->mixer->compressed && output->mixer->pathNode.paths[0].connector.codec == BAVC_AudioCompressionStd_eAc3Plus )
917    {
918        BDBG_ERR(("AC3 Plus audio is not supported on SPDIF"));
919        return BERR_TRACE(BERR_NOT_SUPPORTED);
920    }
921    else
922    {
923        BDBG_MSG(("Starting SPDIF Codec %s", BAPE_P_GetCodecName(output->mixer->pathNode.paths[0].connector.codec)));
924    }
925
926    streamId = GET_SPDIF_STREAM_ID(handle->index);
927    BDBG_MSG(("Enabling %s [stream %u]", handle->name, streamId));
928   
929    /* Write source FCI to IOP */
930    BAPE_Iop_P_GetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
931    streamSettings.resolution = handle->settings.limitTo16Bits?16:24;
932    streamSettings.input = output->sourceMixerFci.ids[BAPE_ChannelPair_eLeftRight];         /* Take source FCI provided from mixer */
933    errCode = BAPE_Iop_P_SetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
934    if ( errCode )
935    {
936        return BERR_TRACE(errCode);
937    }
938   
939    /* Write the enable bit in the OP (only stereo) */
940    BDBG_MSG(("Writing %x to enable set", (BCHP_MASK(AUD_FMM_OP_CTRL_ENABLE_SET, STREAM0_ENA))<<(streamId)));
941    BREG_Write32(handle->deviceHandle->regHandle, 
942                 BCHP_AUD_FMM_OP_CTRL_ENABLE_SET,
943                 (BCHP_MASK(AUD_FMM_OP_CTRL_ENABLE_SET, STREAM0_ENA))<<(streamId));
944
945    BAPE_SpdifOutput_P_SetMute(output, false, false);
946
947    /* Enable this stream in the MS FW */
948    BKNI_EnterCriticalSection();
949    /* Make sure CBITS are correct for current format */
950    BAPE_SpdifOutput_P_SetCbits_isr(handle);
951    /* enable stream 0 */
952    regVal = BREG_Read32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0);
953    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, STREAM_ENA);
954    regVal |= BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, STREAM_ENA, 1);
955    BREG_Write32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, regVal);
956    BKNI_LeaveCriticalSection();
957
958    /* Enable microsequencer */
959    regVal = BREG_Read32(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_STRM_ENA);
960    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_STRM_ENA, STREAM0_ENA);
961    regVal |= BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_STRM_ENA, STREAM0_ENA, 1);
962    BREG_Write32(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_STRM_ENA, regVal);
963
964    handle->enabled = true;
965    return BERR_SUCCESS;
966}
967
968/**************************************************************************/
969
970static void BAPE_SpdifOutput_P_Disable_Legacy(BAPE_OutputPort output)
971{
972    BAPE_SpdifOutputHandle handle;
973    uint32_t regVal;
974    BAPE_IopStreamSettings streamSettings;
975    BERR_Code errCode;
976    unsigned streamId;
977
978    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
979
980    handle = output->pHandle;
981    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
982
983    if ( !handle->enabled )
984    {
985        return;
986    }
987
988    streamId = GET_SPDIF_STREAM_ID(handle->index);
989    BDBG_MSG(("Disabling %s [stream %u]", handle->name, streamId));
990
991    BAPE_SpdifOutput_P_SetMute(output, true, true);
992
993    /* Clear the enable bit in the OP */
994    BDBG_MSG(("Writing %x to enable clear", (BCHP_MASK(AUD_FMM_OP_CTRL_ENABLE_SET, STREAM0_ENA))<<(streamId)));
995    BREG_Write32(handle->deviceHandle->regHandle, 
996                 BCHP_AUD_FMM_OP_CTRL_ENABLE_CLEAR,
997                 BCHP_MASK(AUD_FMM_OP_CTRL_ENABLE_CLEAR, STREAM0_ENA)<<streamId);
998
999    /* Reset source FCI to Invalid */
1000    BAPE_Iop_P_GetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1001    streamSettings.input = BAPE_FCI_ID_INVALID;
1002    errCode = BAPE_Iop_P_SetStreamSettings(handle->deviceHandle, streamId, &streamSettings);
1003    BDBG_ASSERT(BERR_SUCCESS == errCode);
1004
1005    /* Disable microsequencer */
1006    regVal = BREG_Read32(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_STRM_ENA);
1007    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_STRM_ENA, STREAM0_ENA);
1008    BREG_Write32(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_STRM_ENA, regVal);
1009
1010    /* Disable this stream in the MS FW */
1011    BKNI_EnterCriticalSection();
1012    regVal = BREG_Read32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0);
1013    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, STREAM_ENA);
1014    BREG_Write32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, regVal);
1015    BKNI_LeaveCriticalSection();
1016
1017    handle->enabled = false;
1018}
1019
1020/**************************************************************************/
1021
1022static void BAPE_SpdifOutput_P_SetMclk_Legacy_isr(BAPE_OutputPort output, BAPE_MclkSource mclkSource, unsigned pllChannel, unsigned mclkFreqToFsRatio)
1023{
1024    uint32_t regAddr, regVal;
1025    uint32_t pllclksel, mclkRate;
1026
1027    BAPE_SpdifOutputHandle handle;
1028
1029    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
1030
1031    handle = output->pHandle;
1032    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
1033    BDBG_ASSERT(handle->offset == 0);
1034
1035    /* Save the settings in case we need to re-apply them later. */
1036    handle->mclkInfo.mclkSource         = mclkSource;
1037    handle->mclkInfo.pllChannel         = pllChannel;
1038    handle->mclkInfo.mclkFreqToFsRatio  = mclkFreqToFsRatio;
1039
1040    switch ( mclkSource )
1041    {
1042    /* SPDIF Timing */
1043    #if BAPE_CHIP_MAX_PLLS > 0
1044    case BAPE_MclkSource_ePll0:
1045        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_PLL0_ch1 + pllChannel;
1046        break;
1047    #endif
1048    #if BAPE_CHIP_MAX_PLLS > 1
1049    case BAPE_MclkSource_ePll1:
1050        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_PLL1_ch1 + pllChannel;
1051        break;
1052    #endif
1053    #if BAPE_CHIP_MAX_PLLS > 2
1054    case BAPE_MclkSource_ePll2:
1055        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_PLL2_ch1 + pllChannel;
1056        break;
1057    #endif
1058   
1059    /* DAC Timing */
1060    #if BAPE_CHIP_MAX_DACS > 0
1061    case BAPE_MclkSource_eHifidac0:
1062        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_Hifidac0;
1063        break;
1064    #endif
1065    #if BAPE_CHIP_MAX_DACS > 1
1066    case BAPE_MclkSource_eHifidac1:
1067        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_Hifidac1;
1068        break;
1069    #endif
1070    #if BAPE_CHIP_MAX_DACS > 2
1071    case BAPE_MclkSource_eHifidac2:
1072        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_Hifidac2;
1073        break;
1074    #endif
1075   
1076    /* NCO Timing */
1077    #if BAPE_CHIP_MAX_NCOS > 0
1078    case BAPE_MclkSource_eNco0:
1079        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_Mclk_gen0;
1080        break;
1081    #endif
1082    #if BAPE_CHIP_MAX_NCOS > 1
1083    case BAPE_MclkSource_eNco1:
1084        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_Mclk_gen1;
1085        break;
1086    #endif
1087    #if BAPE_CHIP_MAX_NCOS > 2
1088    case BAPE_MclkSource_eNco2:
1089        pllclksel = BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0_PLLCLKSEL_Mclk_gen2;
1090        break;
1091    #endif
1092   
1093    default:
1094        BDBG_ERR(("mclkSource (%u) doesn't refer to a valid PLL or DAC", mclkSource));
1095        BDBG_ASSERT(false);     /* something went wrong somewhere! */
1096        return;
1097    }
1098
1099    /*  PLLs are the recommended timing source for SPDIF, so print a warning if they're using a DAC rate manager. */
1100    if ( BAPE_MCLKSOURCE_IS_DAC(mclkSource) )
1101    {
1102        BDBG_WRN(("DAC timing source has been selected for SPDIF output %u.", handle->index));
1103        BDBG_WRN(("It is strongly recommended to place SPDIF and DAC outputs on separate mixers."));
1104    }
1105    else if ( BAPE_MCLKSOURCE_IS_NCO(mclkSource) )
1106    {
1107        BDBG_WRN(("NCO timing source has been selected for SPDIF output %u.", handle->index));
1108        BDBG_WRN(("It is strongly recommended to use PLL timing for SPDIF."));
1109    }
1110
1111
1112    /* Tell the output formatter how fast our mclk is. */
1113    mclkRate = mclkFreqToFsRatio / ( 128 );  /* mclkRate (for SPDIF) is in multiples of 128Fs */
1114
1115    /* Choose the register for the appropriate output. */
1116    regAddr = GET_SPDIF_REG_ADDR2(BCHP_AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF, handle->index);
1117
1118    /* Read the register and clear the fields that we're going to fill in. */
1119    regVal = BREG_Read32_isr(handle->deviceHandle->regHandle, regAddr);
1120    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0, PLLCLKSEL)|
1121                BCHP_MASK(AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0, MCLK_RATE));
1122
1123    /* Fill in the MCLK_RATE and PLLCLKSEL fields. */
1124    regVal |= BCHP_FIELD_DATA(AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0, MCLK_RATE, mclkRate);
1125    regVal |= BCHP_FIELD_DATA(AUD_FMM_OP_CTRL_MCLK_CFG_SPDIF0, PLLCLKSEL, pllclksel);
1126
1127    /* Then write it to the reg. */
1128    BREG_Write32_isr(handle->deviceHandle->regHandle, regAddr, regVal);
1129}
1130
1131/***************************************************************************
1132        Private functions: Protyped above
1133***************************************************************************/
1134
1135static void BAPE_SpdifOutput_P_SetCbits_Legacy_isr(BAPE_SpdifOutputHandle handle)
1136{
1137    uint32_t regAddr, regVal, cbitAddr, cbitVal, cbitBufAddr;
1138    unsigned i;
1139    bool compressed;
1140    uint16_t cbits[3];
1141
1142    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
1143
1144    compressed = (handle->outputPort.mixer && handle->outputPort.mixer->compressed)?true:false;
1145
1146    BDBG_MSG(("Configuring CBITS for %s", compressed?"Compressed":"PCM"));
1147
1148    regAddr = BCHP_AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0;
1149    regVal = BREG_Read32_isr(handle->deviceHandle->regHandle, regAddr);
1150    regVal &= ~( (BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, CHAN_OVERRIDE)) 
1151                |(BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, DITHER_ENA)) 
1152                |(BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, VALIDITY)) 
1153                |(BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, COMP_OR_LINEAR))
1154                |(BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, SPDIF_OR_PCM))
1155                |(BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, FLUSH_ON_UFLOW))
1156                |(BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, INSERT_ON_UFLOW))
1157                |(BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, INSERT_WHEN_DISA))     
1158                |(BCHP_MASK(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, STREAM_ENA))
1159                );
1160
1161    regVal |= (BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, SPDIF_OR_PCM, 1));
1162    if ( handle->settings.channelStatus.separateLeftRight )
1163    {
1164        regVal |= (BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, CHAN_OVERRIDE, 1));
1165    }
1166    if ( compressed )
1167    {
1168        regVal |= (BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, VALIDITY, 1));
1169        regVal |= (BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, COMP_OR_LINEAR, 1));
1170    } 
1171    else if ( handle->settings.ditherEnabled )
1172    {
1173        regVal |= (BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, DITHER_ENA, 1));
1174    }
1175   
1176    /* RAP programs channel status bits here. */
1177    if ( handle->settings.useRawChannelStatus )
1178    {
1179        cbits[0] = (uint16_t)handle->settings.rawChannelStatus[0] |
1180                (((uint16_t)handle->settings.rawChannelStatus[1])<<8);
1181        cbits[1] = ((uint32_t)handle->settings.rawChannelStatus[2]) |
1182            (((uint32_t)handle->settings.rawChannelStatus[3])<<8);
1183        cbits[2] = 0;
1184    }
1185    else if ( handle->settings.channelStatus.professional )
1186    {
1187        cbits[0] = 0xc000 | (BAPE_P_GetSampleRateCstatCode(handle->sampleRate)<<8);
1188        cbits[1] = cbits[2] = 0;
1189    }
1190    else
1191    {
1192        /* Refer to IEC 60958-3 (5.2.2) */
1193        cbits[0] = (((uint16_t)handle->settings.channelStatus.categoryCode)<<8) |
1194                   (((uint16_t)handle->settings.channelStatus.formatInformation)<<3);
1195        if ( !handle->settings.channelStatus.copyright )
1196        {
1197            cbits[0] |= 1<<2;   /* Copyright = 0, no copyright = 1 in bit 2 */
1198        }
1199        if ( compressed )
1200        {
1201            cbits[0] |= 1<<1;   /* Linear/PCM */
1202        }
1203        cbits[1] = (((uint16_t)handle->settings.channelStatus.clockAccuracy)<<12) |
1204                    (BAPE_P_GetSampleRateCstatCode(handle->sampleRate)<<8) |
1205                    ((uint16_t)handle->settings.channelStatus.sourceNumber) |
1206                    (((uint16_t)handle->settings.channelStatus.separateLeftRight)<<4);
1207        cbits[2] = (((uint16_t)handle->settings.channelStatus.cgmsA)<<8);
1208    }
1209   
1210    /* Load channel status bits into FW registers */
1211    cbitAddr = BCHP_AUD_FMM_MS_CTRL_FW_CBIT_CTRL_0;
1212    cbitVal = BREG_Read32_isr(handle->deviceHandle->regHandle, cbitAddr);
1213    if ( 0x50 == BCHP_GET_FIELD_DATA(cbitVal, AUD_FMM_MS_CTRL_FW_CBIT_CTRL_0, OFFSET) )
1214    {
1215        /* Using ping buffer - Load pong */
1216        cbitBufAddr = BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE + 48;
1217    }
1218    else
1219    {
1220        /* Using pong buffer - Load ping */
1221        cbitBufAddr = BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE;
1222    }
1223    BREG_Write32_isr(handle->deviceHandle->regHandle, cbitBufAddr, cbits[0]);
1224    BREG_Write32_isr(handle->deviceHandle->regHandle, cbitBufAddr+4, cbits[1]);
1225    BREG_Write32_isr(handle->deviceHandle->regHandle, cbitBufAddr+8, cbits[2]);
1226    for ( i = 0; i < 9; i++ )
1227    {
1228        BREG_Write32_isr(handle->deviceHandle->regHandle, cbitBufAddr+12+(4*i), 0);
1229    }
1230    cbitVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_FW_CBIT_CTRL_0, OFFSET);
1231    if ( cbitBufAddr == BCHP_AUD_FMM_MS_CTRL_FW_CBITSi_ARRAY_BASE )
1232    {
1233        cbitVal |= BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_CBIT_CTRL_0, OFFSET, 0x50);
1234    }
1235    else
1236    {
1237        cbitVal |= BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_CBIT_CTRL_0, OFFSET, 0x5c);
1238    }
1239    BREG_Write32_isr(handle->deviceHandle->regHandle, cbitAddr, cbitVal);
1240               
1241    regVal |= (BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, INSERT_ON_UFLOW, 1));
1242    regVal |= (BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, FLUSH_ON_UFLOW, 1));
1243    regVal |= (BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, INSERT_WHEN_DISA, 1));
1244
1245    BREG_Write32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_FW_RAMP_AMOUNT_0, 0);
1246
1247    /* Enable formatter */
1248    regVal |= (BCHP_FIELD_ENUM(AUD_FMM_MS_CTRL_FW_STREAM_CTRL_0, STREAM_ENA, Enable));
1249    BREG_Write32_isr(handle->deviceHandle->regHandle, regAddr, regVal);
1250
1251    /* Disable bypass */
1252    regVal = BREG_Read32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_BYPASS);
1253    regVal &= ~BCHP_MASK(AUD_FMM_MS_CTRL_USEQ_BYPASS, STREAM0);
1254    regVal |= BCHP_FIELD_DATA(AUD_FMM_MS_CTRL_USEQ_BYPASS, STREAM0, 0);
1255    BREG_Write32_isr(handle->deviceHandle->regHandle, BCHP_AUD_FMM_MS_CTRL_USEQ_BYPASS, regVal);
1256
1257    return;
1258}
1259
1260/**************************************************************************/
1261
1262static BERR_Code BAPE_SpdifOutput_P_OpenHw_Legacy(BAPE_SpdifOutputHandle handle)
1263{
1264    BERR_Code       errCode = BERR_SUCCESS;
1265    BAPE_Handle     deviceHandle;
1266    uint32_t        regAddr, regVal;
1267
1268    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
1269
1270    deviceHandle = handle->deviceHandle;
1271    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1272
1273    /* Enable the clock and data while opening the output port. Never disable it */
1274    regAddr = BCHP_AUD_FMM_OP_CTRL_SPDIF_CFG_0 + handle->offset;
1275    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1276    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_SPDIF_CFG_0, CLOCK_ENABLE)|
1277                BCHP_MASK(AUD_FMM_OP_CTRL_SPDIF_CFG_0,DATA_ENABLE));
1278    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_SPDIF_CFG_0, CLOCK_ENABLE, Enable);
1279    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_SPDIF_CFG_0, DATA_ENABLE, Enable);
1280    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1281
1282    return errCode;
1283}
1284
1285/**************************************************************************/
1286
1287static BERR_Code BAPE_SpdifOutput_P_CloseHw_Legacy(BAPE_SpdifOutputHandle handle)
1288{
1289    BERR_Code       errCode = BERR_SUCCESS;
1290    BAPE_Handle     deviceHandle;
1291    uint32_t        regAddr, regVal;
1292
1293    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
1294
1295    deviceHandle = handle->deviceHandle;
1296    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
1297
1298    /* Disable the Spdif clock and data. */
1299    regAddr = BCHP_AUD_FMM_OP_CTRL_SPDIF_CFG_0 + handle->offset;
1300    regVal = BREG_Read32(deviceHandle->regHandle, regAddr);
1301    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_SPDIF_CFG_0, CLOCK_ENABLE)|
1302                BCHP_MASK(AUD_FMM_OP_CTRL_SPDIF_CFG_0,DATA_ENABLE));
1303    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_SPDIF_CFG_0, CLOCK_ENABLE, Disable);
1304    regVal |= BCHP_FIELD_ENUM(AUD_FMM_OP_CTRL_SPDIF_CFG_0, DATA_ENABLE, Disable);
1305    BREG_Write32(deviceHandle->regHandle, regAddr, regVal);
1306
1307    return errCode;
1308}
1309
1310static BERR_Code BAPE_SpdifOutput_P_ApplySettings_Legacy(
1311    BAPE_SpdifOutputHandle handle,
1312    const BAPE_SpdifOutputSettings *pSettings,
1313    bool force
1314    )
1315{
1316    uint32_t regAddr, regVal;
1317
1318    BSTD_UNUSED(force); /* Not used because HW gets updated unconditionally */
1319
1320    BDBG_OBJECT_ASSERT(handle, BAPE_SpdifOutput);
1321    BDBG_ASSERT(NULL != pSettings);
1322   
1323    regAddr = BCHP_AUD_FMM_OP_CTRL_SPDIF_CFG_0 + handle->offset;
1324    regVal = BREG_Read32(handle->deviceHandle->regHandle, regAddr);
1325    regVal &= ~(BCHP_MASK(AUD_FMM_OP_CTRL_SPDIF_CFG_0, LR_SELECT)|
1326                BCHP_MASK(AUD_FMM_OP_CTRL_SPDIF_CFG_0, LIMIT_TO_16_BITS));
1327    regVal |= BCHP_FIELD_DATA(AUD_FMM_OP_CTRL_SPDIF_CFG_0, LR_SELECT, pSettings->stereoMode);
1328    regVal |= BCHP_FIELD_DATA(AUD_FMM_OP_CTRL_SPDIF_CFG_0, LIMIT_TO_16_BITS, (pSettings->limitTo16Bits?1:0));
1329    BREG_Write32(handle->deviceHandle->regHandle, regAddr, regVal);
1330   
1331    handle->settings = *pSettings;
1332    /* Remaining fields are handled by MS regs.  Must modify those in critical section. */   
1333    BKNI_EnterCriticalSection();
1334    BAPE_SpdifOutput_P_SetCbits_isr(handle);
1335    BKNI_LeaveCriticalSection();
1336
1337    return BERR_SUCCESS;
1338}
1339#endif
1340
1341#else
1342
1343void BAPE_SpdifOutput_GetDefaultSettings(
1344    BAPE_SpdifOutputSettings *pSettings
1345    )
1346{
1347    BSTD_UNUSED(pSettings);
1348}
1349
1350BERR_Code BAPE_SpdifOutput_Open(
1351    BAPE_Handle deviceHandle,
1352    unsigned index,
1353    const BAPE_SpdifOutputSettings *pSettings,
1354    BAPE_SpdifOutputHandle *pHandle             /* [out] */
1355    )
1356{
1357    BSTD_UNUSED(pSettings);
1358    BSTD_UNUSED(deviceHandle);
1359    BSTD_UNUSED(index);
1360    BSTD_UNUSED(pHandle);
1361    return BERR_TRACE(BERR_NOT_SUPPORTED);
1362}
1363
1364
1365void BAPE_SpdifOutput_Close(
1366    BAPE_SpdifOutputHandle handle
1367    )
1368{
1369    BSTD_UNUSED(handle);
1370}
1371
1372void BAPE_SpdifOutput_GetSettings(
1373    BAPE_SpdifOutputHandle handle,
1374    BAPE_SpdifOutputSettings *pSettings     /* [out] */
1375    )
1376{
1377    BSTD_UNUSED(handle);
1378    BSTD_UNUSED(pSettings);
1379}
1380
1381
1382BERR_Code BAPE_SpdifOutput_SetSettings(
1383    BAPE_SpdifOutputHandle handle,
1384    const BAPE_SpdifOutputSettings *pSettings
1385    )
1386{
1387    BSTD_UNUSED(handle);
1388    BSTD_UNUSED(pSettings);
1389    return BERR_TRACE(BERR_NOT_SUPPORTED);
1390}
1391
1392void BAPE_SpdifOutput_GetOutputPort(
1393    BAPE_SpdifOutputHandle handle,
1394    BAPE_OutputPort *pOutputPort        /* [out] */
1395    )
1396{
1397    BSTD_UNUSED(handle);
1398    BSTD_UNUSED(pOutputPort);
1399    (void)BERR_TRACE(BERR_NOT_SUPPORTED);
1400}
1401
1402#endif
1403
1404#if BAPE_CHIP_MAX_SPDIF_OUTPUTS > 0 || BAPE_CHIP_MAX_MAI_OUTPUTS > 0
1405/***************************************************************************
1406Summary:
1407Setup Channel Status Bits for SPDIF or HDMI outputs
1408***************************************************************************/
1409void BAPE_P_MapSpdifChannelStatusToBits_isr(
1410    BAPE_OutputPort output,
1411    const BAPE_SpdifChannelStatus *pChannelStatus,
1412    BAPE_Spdif_P_ChannelStatusBits *pBits           /* [out] */
1413    )
1414{
1415    bool compressed;
1416    unsigned sampleRate;
1417
1418    BDBG_OBJECT_ASSERT(output, BAPE_OutputPort);
1419    BDBG_ASSERT(NULL != pChannelStatus);
1420    BDBG_ASSERT(NULL != pBits);
1421
1422    pBits->bits[0] = 0;
1423    pBits->bits[1] = 0;
1424    pBits->bits[2] = 0;
1425
1426    if ( output->mixer )
1427    {
1428        compressed = output->mixer->compressed;
1429        sampleRate = output->mixer->sampleRate;
1430    }
1431    else
1432    {
1433        compressed = false;
1434        sampleRate = 48000;
1435    }
1436   
1437    if ( pChannelStatus->professional )
1438    {
1439        pBits->bits[0] |= 0x01 <<  0;   /* PRO_CONS */
1440    }
1441    if ( compressed )
1442    {
1443        pBits->bits[0] |= 0x01 <<  1;   /* COMP_LIN */
1444    }
1445    if ( !pChannelStatus->copyright )
1446    {
1447        pBits->bits[0] |= 0x01 <<  2;   /* CP */
1448    }
1449    /* EMPH = 0 */
1450    /* CMODE = 0 */
1451    pBits->bits[0] |= ((uint32_t)pChannelStatus->categoryCode&0xff) <<  8;   /* CATEGORY */
1452    pBits->bits[0] |= ((uint32_t)pChannelStatus->sourceNumber&0x0f) << 16;   /* SOURCE */
1453    pBits->bits[0] |= ((uint32_t)BAPE_P_GetSampleRateCstatCode(sampleRate)) << 24;   /* FREQ */
1454    pBits->bits[0] |= ((uint32_t)pChannelStatus->clockAccuracy&0x03) << 28;   /* ACCURACY */
1455    /* FREQ_EXTN = 0 */
1456
1457    if ( compressed ) 
1458    {
1459        /* Compressed leaves word1 at 0 */
1460    }
1461    else
1462    {
1463        pBits->bits[1] |= 0x01 << 0;   /* MAX_LEN = 24 bits */
1464        /* LENGTH = 0 [not indicated] */
1465        /* ORIG_FREQ = 0 [not indicated] */
1466        pBits->bits[1] |= ((uint32_t)pChannelStatus->cgmsA&0x03) << 8;   /* CGMS_A */
1467    }
1468
1469    /* Done */
1470}
1471
1472#endif
1473
Note: See TracBrowser for help on using the repository browser.