source: svn/newcon3bcm2_21bu/nexus/modules/audio/7552/src/nexus_audio_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: 42.3 KB
Line 
1/***************************************************************************
2*     (c)2004-2011 Broadcom Corporation
3*
4*  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5*  and may only be used, duplicated, modified or distributed pursuant to the terms and
6*  conditions of a separate, written license agreement executed between you and Broadcom
7*  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8*  no license (express or implied), right to use, or waiver of any kind with respect to the
9*  Software, and Broadcom expressly reserves all rights in and to the Software and all
10*  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11*  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12*  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13*
14*  Except as expressly set forth in the Authorized License,
15*
16*  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17*  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18*  and to use this information only in connection with your use of Broadcom integrated circuit products.
19*
20*  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21*  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22*  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23*  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24*  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25*  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26*  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27*  USE OR PERFORMANCE OF THE SOFTWARE.
28*
29*  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30*  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31*  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32*  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33*  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34*  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35*  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36*  ANY LIMITED REMEDY.
37*
38* $brcm_Workfile: nexus_audio_output.c $
39* $brcm_Revision: 19 $
40* $brcm_Date: 11/18/11 2:47p $
41*
42* API Description:
43*   Private routines internal to the audio module
44*
45* Revision History:
46*
47* $brcm_Log: /nexus/modules/audio/7422/src/nexus_audio_output.c $
48*
49* 19   11/18/11 2:47p jgarrett
50* SW7425-1757: Propagating channel status information to APE
51*
52* 18   9/8/11 8:45a jgarrett
53* SWDTV-6627: Adding nexus EQ support
54*
55* 17   9/1/11 9:32a ialauder
56* SWDTV-8471: NEXUS_AudioReturnChannel_P_SetMaster was called with params
57*  in reversed order.  Also need to prevent setting volume if we have a
58*  slave output.
59*
60* 16   7/13/11 12:15p gskerl
61* SW7425-884: Re-checked in: Added support for NCO/Mclkgen audio clock
62*  sources
63*
64* 15   7/10/11 10:24p gskerl
65* SW7552-72: Reverted previous checkin (waiting until APE label is moved)
66*
67* 14   7/8/11 4:32p gskerl
68* SW7552-72: Added support for NCO/Mclkgen audio clock sources
69*
70* 13   7/6/11 6:41p jgarrett
71* SW7552-55: Mapping channelMode to stereoMode
72*
73* 12   6/30/11 6:24p jgarrett
74* SW7346-206: Caching HDMI sample rate from last sample rate callback and
75*  not resetting to default on disconnection
76*
77* 11   5/25/11 5:16p jgarrett
78* SW7425-408: Adding BDBG_OBJECT to input/output types and MS11 features
79*
80* 10   5/13/11 2:06p gskerl
81* SW7422-354: Added APE support for Audio Return Channel
82*
83* 9   4/26/11 11:35a jgarrett
84* SW7425-437: Resolving kernel mode shutdown issues
85*
86* 8   4/6/11 11:39a jgarrett
87* SW35330-35: Stubbing out ARC and making HDMI output optional
88*
89* 7   3/21/11 7:05p jgarrett
90* SW7422-356: Adding MuxOutput support in APE/Nexus
91*
92* 6   3/3/11 8:09p jgarrett
93* SW7422-146: Fixing DDP passthrough sample rate issue
94*
95* 5   3/3/11 6:32p jgarrett
96* SW7422-146: Fixing issue with HDMI sample rate being stuck at a
97*  previous value
98*
99* 4   2/22/11 5:44p jgarrett
100* SW7422-146: Implemented type renaming based on filter graph review
101*  comments
102*
103* 3   1/27/11 5:47p jgarrett
104* SW7422-146: Removing warning of bad hdmi sample rate
105*
106* 2   1/21/11 10:58a jgarrett
107* SW7422-146: Fixing HDMI sample rate
108*
109* 1   12/17/10 3:56p jgarrett
110* SW7422-146: Adding initial nexus on APE for 7422
111*
112***************************************************************************/
113#include "nexus_audio_module.h"
114#include "priv/nexus_audio_output_priv.h"
115#if NEXUS_NUM_HDMI_OUTPUTS
116#include "nexus_hdmi_output.h"
117#include "priv/nexus_hdmi_output_priv.h"
118static struct
119{
120    NEXUS_AudioOutput output;
121    BAPE_MaiOutputHandle handle;
122    BKNI_EventHandle settingsChangedEvent;
123    NEXUS_EventCallbackHandle settingsChangedCallback;
124} g_hdmiMapping[NEXUS_NUM_HDMI_OUTPUTS];
125
126static void NEXUS_AudioOutput_P_HdmiSettingsChanged(void *pOutput);
127static void NEXUS_AudioOutput_P_HdmiSampleRateChange_isr(void *, int, unsigned);
128#define NEXUS_AudioOutput_P_GetSampleRateEnum NEXUS_AudioOutput_P_GetSampleRateEnum_isr
129static BAVC_AudioSamplingRate NEXUS_AudioOutput_P_GetSampleRateEnum_isr(unsigned sampleRate)
130{
131    switch ( sampleRate )
132    {
133    case 32000:
134        return BAVC_AudioSamplingRate_e32k;    /* 32K Sample rate */
135    case 44100:
136        return BAVC_AudioSamplingRate_e44_1k;    /* 44.1K Sample rate */
137    case 48000:
138        return BAVC_AudioSamplingRate_e48k;      /* 48K Sample rate */
139    case 96000:
140        return BAVC_AudioSamplingRate_e96k;      /* 96K Sample rate */
141    case 16000:
142        return BAVC_AudioSamplingRate_e16k;      /* 16K Sample rate */
143    case 22050:
144        return BAVC_AudioSamplingRate_e22_05k;   /* 22.05K Sample rate */
145    case 24000:
146        return BAVC_AudioSamplingRate_e24k;      /* 24K Sample rate */
147    case 64000:
148        return BAVC_AudioSamplingRate_e64k;      /* 64K Sample rate */
149    case 88200:
150        return BAVC_AudioSamplingRate_e88_2k;    /* 88.2K Sample rate */
151    case 128000:
152        return BAVC_AudioSamplingRate_e128k;     /* 128K Sample rate */
153    case 176400:
154        return BAVC_AudioSamplingRate_e176_4k;   /* 176.4K Sample rate */
155    case 192000:
156        return BAVC_AudioSamplingRate_e192k;     /* 192K Sample rate */
157    case 8000:
158        return BAVC_AudioSamplingRate_e8k;       /* 8K Sample rate */
159    case 12000:
160        return BAVC_AudioSamplingRate_e12k;      /* 12K Sample rate */
161    case 11025:
162        return BAVC_AudioSamplingRate_e11_025k;  /* 11.025K Sample rate */
163    default:
164        return 0;
165    }
166}
167#endif
168#if NEXUS_NUM_RFM_OUTPUTS
169#include "priv/nexus_rfm_priv.h"
170static struct
171{
172    NEXUS_AudioOutput output;
173    BAPE_RfModHandle handle;
174} g_rfmMapping[NEXUS_NUM_RFM_OUTPUTS];
175#endif
176#if 0 /* TODO */
177#include "bchp_vcxo_0_rm.h"
178#include "bchp_vcxo_ctl_misc.h"
179#endif
180
181BDBG_MODULE(nexus_audio_output);
182
183BDBG_OBJECT_ID(NEXUS_AudioOutputData);
184
185
186/******************************************************************************
187The array to represent the value of volume in hex corresponding to the value
188in DB. The application inputs the volume in terms of DB and the Corresponding
189HEX value is mentioned here. The formula used for the same is:
190
191    HEX = (2^23) * 10^(DB/20)
192
193Note: 23 is the number of bits in the volume control field.
194
195The volume can range from 0-1. 0 in hex corresponds to the 139 DB from the above
196Formula. If application enters more than this value, it is forced to 0.
197******************************************************************************/
198static const int32_t g_db2linear[] =
199{
200    0x800000,   0x721482,   0x65AC8C,   0x5A9DF7,   0x50C335,
201    0x47FACC,   0x4026E7,   0x392CED,   0x32F52C,   0x2D6A86,
202    0x287A26,   0x241346,   0x2026F3,   0x1CA7D7,   0x198A13,
203    0x16C310,   0x144960,   0x12149A,   0x101D3F,   0xE5CA1,
204    0xCCCCC,    0xB6873,    0xA2ADA,    0x90FCB,    0x81385,
205    0x732AE,    0x66A4A,    0x5B7B1,    0x51884,    0x48AA7,
206    0x40C37,    0x39B87,    0x33718,    0x2DD95,    0x28DCE,
207    0x246B4,    0x20756,    0x1CEDC,    0x19C86,    0x16FA9,
208    0x147AE,    0x1240B,    0x10449,    0xE7FA,     0xCEC0,
209    0xB844,     0xA43A,     0x925E,     0x8273,     0x7443,
210    0x679F,     0x5C5A,     0x524F,     0x495B,     0x4161,
211    0x3A45,     0x33EF,     0x2E49,     0x2940,     0x24C4,
212    0x20C4,     0x1D34,     0x1A07,     0x1732,     0x14AC,
213    0x126D,     0x106C,     0xEA3,      0xD0B,      0xBA0,
214    0xA5C,      0x93C,      0x83B,      0x755,      0x689,
215    0x5D3,      0x531,      0x4A0,      0x420,      0x3AD,
216    0x346,      0x2EB,      0x29A,      0x251,      0x211,
217    0x1D7,      0x1A4,      0x176,      0x14D,      0x129,
218    0xEC,       0xD2,       0xA7,       0x95,       0x84,
219    0x76,       0x69,       0x5E,       0x53,       0x4A,
220    0x42,       0x3B,       0x34,       0x2F,       0x2A,
221    0x25,       0x21,       0x1D,       0x1A,       0x17,
222    0x15,       0x12,       0x10,       0xE,        0xD,
223    0xB,        0xA,        0x9,        0x8,        0x7,
224    0x6,        0x5,        0x5,        0x4,        0x4,
225    0x3,        0x3,        0x2,        0x2,        0x2,
226    0x2,        0x1,        0x1,        0x1,        0x1,
227    0x1,        0x1,        0x1,        0x0
228};
229
230static int32_t NEXUS_AudioOutput_P_Vol2Magnum(NEXUS_AudioVolumeType type, int32_t volume)
231{
232    if ( type == NEXUS_AudioVolumeType_eDecibel )
233    {
234        int32_t linearVol;
235        int volumeIndex;
236        if ( volume > 0 )
237        {
238            BDBG_ERR(("Currently, amplification is not supported for dB values.  Clipping to 0 dB"));
239            return 0;
240        }
241        else if ( volume < NEXUS_AUDIO_VOLUME_DB_MIN )
242        {
243            BDBG_ERR(("Clipping out of range volume to minimum"));
244            return NEXUS_AUDIO_VOLUME_LINEAR_MIN;
245        }
246        else if ( volume == NEXUS_AUDIO_VOLUME_DB_MIN )
247        {
248            return NEXUS_AUDIO_VOLUME_LINEAR_MIN;
249        }
250
251        /* Convert dB attenuation to linear gain.  Start by Flipping the sign */
252        volume = -volume;
253
254        /* Grab integer portion */
255        volumeIndex = volume/100;
256        linearVol = g_db2linear[volumeIndex];
257        /* Grab fractional portion */
258        volume = volume % 100;
259        /* Linearly interpolate between the two levels */
260        linearVol -= ((g_db2linear[volumeIndex]-g_db2linear[volumeIndex+1])*volume)/100;
261
262        return linearVol;
263    }
264    else
265    {
266        if ( volume < NEXUS_AUDIO_VOLUME_LINEAR_MIN )
267        {
268            BDBG_ERR(("Clipping out of range volume to minimum"));
269            return NEXUS_AUDIO_VOLUME_LINEAR_MIN;
270        }
271#if 0 /* Permitting amplification */
272        /* The destination APIs are linear now.  No conversion required!! */
273        else if ( volume > NEXUS_AUDIO_VOLUME_LINEAR_NORMAL )
274        {
275            BDBG_ERR(("This platform does not support amplification.  Volume will be set to normal"));
276            return NEXUS_AUDIO_VOLUME_LINEAR_NORMAL;
277        }
278#endif
279
280        return volume;
281    }
282}
283
284/***************************************************************************
285Summary:
286    Get default settings for an audio output
287See Also:
288    NEXUS_AudioOutput_Open
289 ***************************************************************************/
290void NEXUS_AudioOutput_GetDefaultSettings(
291    NEXUS_AudioOutputSettings *pSettings      /* [out] Settings */
292    )
293{
294    BKNI_Memset(pSettings, 0, sizeof(NEXUS_AudioOutputSettings));
295    pSettings->defaultSampleRate = 48000;
296    pSettings->pll = g_NEXUS_audioModuleData.settings.defaultPll;
297    pSettings->nco = NEXUS_AudioOutputNco_eMax;    /* eMax => don't use an NCO */
298    pSettings->leftVolume = NEXUS_AUDIO_VOLUME_DB_NORMAL;
299    pSettings->rightVolume = NEXUS_AUDIO_VOLUME_DB_NORMAL;
300}
301
302/***************************************************************************
303Summary:
304    Get settings of an audio output
305See Also:
306    NEXUS_AudioOutput_SetSettings
307 ***************************************************************************/
308void NEXUS_AudioOutput_GetSettings(
309    NEXUS_AudioOutput output,
310    NEXUS_AudioOutputSettings *pSettings    /* [out] Current Settings */
311    )
312{
313    NEXUS_AudioOutputData *pData;
314
315    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
316    BDBG_ASSERT(NULL != pSettings);
317
318    if ( NULL == output->pMixerData )
319    {
320        NEXUS_AudioOutput_GetDefaultSettings(pSettings);
321        return;
322    }
323
324    pData = output->pMixerData;
325    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
326    *pSettings = pData->settings;
327
328    /* Success */
329}
330
331/***************************************************************************
332Summary:
333    Set settings of an audio output
334See Also:
335    NEXUS_AudioOutput_GetSettings
336 ***************************************************************************/
337NEXUS_Error NEXUS_AudioOutput_SetSettings(
338    NEXUS_AudioOutput output,
339    const NEXUS_AudioOutputSettings *pSettings
340    )
341{
342    BAPE_OutputVolume volume;
343    NEXUS_Error errCode;
344    NEXUS_AudioOutputSettings defaultSettings;
345    NEXUS_AudioOutputData *pData;
346    int i;
347    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
348
349    if ( NULL == pSettings )
350    {
351        NEXUS_AudioOutput_GetDefaultSettings(&defaultSettings);
352        pSettings = &defaultSettings;
353    }
354
355    if ( NULL == output->pMixerData )
356    {
357        pData = NEXUS_AudioOutput_P_CreateData(output);
358        if ( NULL == pData )
359        {
360            return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
361        }
362    }
363
364    pData = output->pMixerData;
365    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
366
367    if ( !(NEXUS_AudioOutput_P_IsDacSlave(output) || NEXUS_AudioOutput_P_IsSpdifSlave(output)) )
368    {
369        /* We can apply volume immediately.  Do that here. */
370        BAPE_GetOutputVolume((BAPE_OutputPort)output->port, &volume);
371        for ( i = 0; i < BAPE_ChannelPair_eMax; i++ )
372        {
373            volume.volume[i*2] = NEXUS_AudioOutput_P_Vol2Magnum(pSettings->volumeType, pSettings->leftVolume);
374            volume.volume[(i*2)+1] = NEXUS_AudioOutput_P_Vol2Magnum(pSettings->volumeType, pSettings->rightVolume);
375        }
376        volume.muted = pSettings->muted || pData->trickMute;
377        errCode = BAPE_SetOutputVolume((BAPE_OutputPort)output->port, &volume);
378        if ( errCode )
379        {
380            return BERR_TRACE(errCode);
381        }
382    }
383    /* Apply channel mode if required */
384    if ( output->setChannelMode )
385    {
386        errCode = output->setChannelMode(output->pObjectHandle, pSettings->channelMode);
387        if ( errCode )
388        {
389            return BERR_TRACE(errCode);
390        }
391    }
392#if NEXUS_NUM_HDMI_OUTPUTS > 0
393    else if ( output->objectType == NEXUS_AudioOutputType_eHdmi )
394    {
395        for ( i = 0; i < NEXUS_NUM_HDMI_OUTPUTS; i++ )
396        {
397            if ( g_hdmiMapping[i].output == output )
398            {
399                BAPE_MaiOutputSettings maiOutputSettings;
400                NEXUS_HdmiOutputSettings hdmiSettings;
401                BAPE_MaiOutput_GetSettings(g_hdmiMapping[i].handle, &maiOutputSettings);
402                switch ( pSettings->channelMode )
403                {
404                default:
405                case NEXUS_AudioChannelMode_eStereo:
406                    maiOutputSettings.stereoMode = BAPE_StereoMode_eLeftRight;
407                    break;
408                case NEXUS_AudioChannelMode_eLeft:
409                    maiOutputSettings.stereoMode = BAPE_StereoMode_eLeftLeft;
410                    break;
411                case NEXUS_AudioChannelMode_eRight:
412                    maiOutputSettings.stereoMode = BAPE_StereoMode_eRightRight;
413                    break;
414                case NEXUS_AudioChannelMode_eSwapped:
415                    maiOutputSettings.stereoMode = BAPE_StereoMode_eRightLeft;
416                    break;
417                }
418
419                /* Remaining settings need to be pulled from the HDMI output */
420                NEXUS_HdmiOutput_GetSettings(output->pObjectHandle, &hdmiSettings);
421                maiOutputSettings.channelStatus.professional = hdmiSettings.audioChannelStatusInfo.professionalMode;
422                maiOutputSettings.channelStatus.copyright = hdmiSettings.audioChannelStatusInfo.swCopyRight;
423                maiOutputSettings.channelStatus.categoryCode = hdmiSettings.audioChannelStatusInfo.categoryCode;
424                maiOutputSettings.channelStatus.clockAccuracy = hdmiSettings.audioChannelStatusInfo.clockAccuracy;
425                maiOutputSettings.channelStatus.separateLeftRight = hdmiSettings.audioChannelStatusInfo.separateLRChanNum;
426                maiOutputSettings.ditherEnabled = hdmiSettings.audioDitherEnabled;
427
428                errCode = BAPE_MaiOutput_SetSettings(g_hdmiMapping[i].handle, &maiOutputSettings);
429                if ( errCode )
430                {
431                    return BERR_TRACE(errCode);
432                }
433                break;
434            }
435        }
436    }
437#endif
438
439    /* Store settings */
440    pData->settings = *pSettings;
441
442    /* Applying remaining settings should be deferred until the next start call if we're running. */
443    if ( pData->input )
444    {
445        NEXUS_AudioInput_P_OutputSettingsChanged(pData->input, output);
446    }
447
448    return BERR_SUCCESS;
449}
450
451/***************************************************************************
452Summary:
453    Add an input to this output
454See Also:
455    NEXUS_AudioOutput_RemoveInput
456    NEXUS_AudioOutput_RemoveAllInputs
457 ***************************************************************************/
458NEXUS_Error NEXUS_AudioOutput_AddInput(
459    NEXUS_AudioOutput output,
460    NEXUS_AudioInput input
461    )
462{
463    NEXUS_Error errCode;
464    NEXUS_AudioOutputData *pData;
465
466    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
467    BDBG_OBJECT_ASSERT(input, NEXUS_AudioInput);
468
469    if ( NULL == output->pMixerData )
470    {
471        pData = NEXUS_AudioOutput_P_CreateData(output);
472        if ( NULL == pData )
473        {
474            return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
475        }
476    }
477
478    pData = output->pMixerData;
479    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
480
481    if ( pData->input != NULL )
482    {
483        BDBG_WRN(("Input %p is already connected to this output", output->pMixerData));
484        return BERR_TRACE(BERR_NOT_SUPPORTED);
485    }
486
487    if ( NEXUS_AudioInput_P_IsRunning(input) )
488    {
489        BDBG_WRN(("Input %p is running.  Please stop first.", input));
490        return BERR_TRACE(BERR_NOT_SUPPORTED);
491    }
492
493    errCode = NEXUS_AudioInput_P_ConnectOutput(input, output);
494    if ( errCode )
495    {
496        return BERR_TRACE(errCode);
497    }
498
499    pData->input = input;
500
501    return BERR_SUCCESS;
502}
503
504/***************************************************************************
505Summary:
506    Add an input to this output
507See Also:
508    NEXUS_AudioOutput_AddInput
509    NEXUS_AudioOutput_RemoveAllInputs
510 ***************************************************************************/
511NEXUS_Error NEXUS_AudioOutput_RemoveInput(
512    NEXUS_AudioOutput output,
513    NEXUS_AudioInput input
514    )
515{
516    NEXUS_Error errCode;
517    NEXUS_AudioOutputData *pData;
518
519    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
520    BDBG_OBJECT_ASSERT(input, NEXUS_AudioInput);
521
522    pData = output->pMixerData;
523
524    if ( NULL == pData || input != pData->input )
525    {
526        BDBG_ERR(("Input %p is not connected to this output.", input));
527        return BERR_TRACE(BERR_INVALID_PARAMETER);
528    }
529    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
530
531    if ( NEXUS_AudioInput_P_IsRunning(input) )
532    {
533        BDBG_WRN(("Forcing input %p to stop on output %p shutdown", input, output));
534        NEXUS_AudioInput_P_ForceStop(input);
535    }
536   
537    errCode = NEXUS_AudioInput_P_DisconnectOutput(input, output);
538    if ( errCode )
539    {
540        return BERR_TRACE(errCode);
541    }
542
543    pData->input = NULL;
544    return BERR_SUCCESS;
545}
546
547/***************************************************************************
548Summary:
549    Add an input to this output
550See Also:
551    NEXUS_AudioOutput_AddInput
552    NEXUS_AudioOutput_RemoveInput
553 ***************************************************************************/
554NEXUS_Error NEXUS_AudioOutput_RemoveAllInputs(
555    NEXUS_AudioOutput output
556    )
557{
558    NEXUS_AudioOutputData *pData;
559
560    BDBG_ASSERT(NULL != output);
561
562    pData = output->pMixerData;
563    if ( pData && NULL != pData->input )
564    {
565        NEXUS_Error errCode;
566
567        BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
568        errCode = NEXUS_AudioOutput_RemoveInput(output, pData->input);
569        if ( errCode )
570        {
571            return BERR_TRACE(errCode);
572        }
573    }
574
575    return BERR_SUCCESS;;
576}
577
578/***************************************************************************
579Summary:
580    Shutdown this output handle
581Description:
582    This routine should be called before the specific output object
583    (e.g. AudioDac) is closed.
584See Also:
585    NEXUS_AudioOutput_AddInput
586    NEXUS_AudioOutput_RemoveInput
587 ***************************************************************************/
588void NEXUS_AudioOutput_Shutdown(
589    NEXUS_AudioOutput output
590    )
591{
592    NEXUS_AudioOutputData *pData;
593
594    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
595
596    pData = output->pMixerData;
597    if ( pData )
598    {
599        NEXUS_Error rc;
600
601        BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
602
603        rc = NEXUS_AudioOutput_RemoveAllInputs(output);
604        if (rc) {
605            /* we cannot complete the shutdown */
606            return;
607        }
608        if ( pData->equalizer )
609        {
610            rc = NEXUS_AudioOutput_SetEqualizer(output, NULL);
611            if (rc) {
612                /* we cannot complete the shutdown */
613                return;
614            }
615        }
616
617        BDBG_OBJECT_DESTROY(pData, NEXUS_AudioOutputData);
618        BKNI_Free(pData);
619
620        /* TODO: Handle RFM object handles */
621        switch ( output->objectType )
622        {
623#if NEXUS_NUM_HDMI_OUTPUTS
624        case NEXUS_AudioOutputType_eHdmi:
625            {
626                int i;
627                for ( i = 0; i < NEXUS_NUM_HDMI_OUTPUTS; i++ )
628                {
629                    if ( g_hdmiMapping[i].output == output )
630                    {
631                        output->port = 0;
632                        BDBG_MSG(("Closing MAI output"));
633                        BAPE_MaiOutput_Close(g_hdmiMapping[i].handle);
634
635                        NEXUS_Module_Lock(g_NEXUS_audioModuleData.settings.modules.hdmiOutput);
636                        NEXUS_HdmiOutput_SetNotifyAudioEvent_priv(output->pObjectHandle, NULL);
637                        NEXUS_Module_Unlock(g_NEXUS_audioModuleData.settings.modules.hdmiOutput);
638
639                        NEXUS_UnregisterEvent(g_hdmiMapping[i].settingsChangedCallback);
640                        BKNI_DestroyEvent(g_hdmiMapping[i].settingsChangedEvent);
641                        BKNI_Memset(&g_hdmiMapping[i], 0, sizeof(g_hdmiMapping[i]));
642                        break;
643                    }
644                }
645                BDBG_ASSERT(i < NEXUS_NUM_HDMI_OUTPUTS);
646            }
647            break;
648#endif
649#if NEXUS_NUM_RFM_OUTPUTS
650        case NEXUS_AudioOutputType_eRfm:
651            {
652                int i;
653                for ( i = 0; i < NEXUS_NUM_RFM_OUTPUTS; i++ )
654                {
655                    if ( g_rfmMapping[i].output == output )
656                    {
657                        output->port = 0;
658                        BDBG_MSG(("Closing RFM output"));
659                        BAPE_RfMod_Close(g_rfmMapping[i].handle);
660                        g_rfmMapping[i].output = NULL;
661                        g_rfmMapping[i].handle = NULL;
662                        break;
663                    }
664                }
665                BDBG_ASSERT(i < NEXUS_NUM_RFM_OUTPUTS);
666            }
667            break;
668#endif
669        default:
670            break;
671        }
672    }
673    output->pMixerData = NULL;
674
675    return ;
676}
677
678/***************************************************************************
679Summary:
680    Determine if an output must be tied to a DAC
681Description:
682    Some outputs (i.e. RFM) are slaves to a DAC.
683 ***************************************************************************/
684bool NEXUS_AudioOutput_P_IsDacSlave(
685    NEXUS_AudioOutput output
686    )
687{
688    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
689    return (output->objectType == NEXUS_AudioOutputType_eRfm) ? true : false;
690}
691
692/***************************************************************************
693Summary:
694    Determine if an output must be tied to a SPDIF port
695Description:
696    Some outputs (i.e. ARC) are slaves to a SPDIF port.
697 ***************************************************************************/
698bool NEXUS_AudioOutput_P_IsSpdifSlave(
699    NEXUS_AudioOutput output
700    )
701{
702    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
703    return (output->objectType == NEXUS_AudioOutputType_eArc) ? true : false;
704}
705
706/***************************************************************************
707Summary:
708    For slave outputs, set the DAC source
709Description:
710    Some outputs (i.e. RFM) are slaves to a DAC.  Mixer will find the proper
711    DAC to bind the output to and provide it here.
712 ***************************************************************************/
713NEXUS_Error NEXUS_AudioOutput_P_SetSlaveSource(
714    NEXUS_AudioOutput slaveHandle,
715    NEXUS_AudioOutput sourceHandle)
716{
717    BDBG_OBJECT_ASSERT(slaveHandle, NEXUS_AudioOutput);
718    BSTD_UNUSED(sourceHandle);  /* In case neither of the cases below are defined */
719
720    if ( NEXUS_AudioOutput_P_IsDacSlave(slaveHandle) )
721    {
722        #if NEXUS_NUM_RFM_OUTPUTS
723        NEXUS_RfmConnectionSettings rfmConnectionSettings;
724        bool enabled=false;
725        NEXUS_Error errCode;
726        BAPE_RfModHandle apeRfmHandle=NULL;
727        BAPE_RfModSettings apeRfmSettings;
728        int i;
729
730        if ( NULL == g_NEXUS_audioModuleData.settings.modules.rfm )
731        {
732            return BERR_TRACE(BERR_NOT_SUPPORTED);
733        }
734
735        for ( i = 0; i < NEXUS_NUM_RFM_OUTPUTS; i++ )
736        {
737            if ( g_rfmMapping[i].output == slaveHandle )
738            {
739                apeRfmHandle = g_rfmMapping[i].handle;
740                break;
741            }
742        }
743
744        BDBG_ASSERT(NULL != apeRfmHandle);
745
746        BAPE_RfMod_GetSettings(apeRfmHandle, &apeRfmSettings);
747
748        if ( NULL == sourceHandle )
749        {
750            apeRfmSettings.master = NULL;
751            apeRfmSettings.muted = true;
752        }
753        else
754        {
755            BDBG_ASSERT(sourceHandle->objectType == NEXUS_AudioOutputType_eDac);
756            enabled = true;
757            apeRfmSettings.master = (BAPE_OutputPort)sourceHandle->port;
758            apeRfmSettings.muted = false;
759        }
760
761        errCode = BAPE_RfMod_SetSettings(apeRfmHandle, &apeRfmSettings);
762        if ( errCode )
763        {
764            return BERR_TRACE(errCode);
765        }
766
767        /* Tell RFM to mute or unmute appropriately */
768        NEXUS_Module_Lock(g_NEXUS_audioModuleData.settings.modules.rfm);
769        NEXUS_Rfm_GetConnectionSettings_priv(slaveHandle->pObjectHandle, &rfmConnectionSettings);
770        rfmConnectionSettings.audioEnabled = enabled;
771        errCode = NEXUS_Rfm_SetConnectionSettings_priv(slaveHandle->pObjectHandle, &rfmConnectionSettings);
772        NEXUS_Module_Unlock(g_NEXUS_audioModuleData.settings.modules.rfm);
773
774        if ( errCode )
775        {
776            return BERR_TRACE(errCode);
777        }
778        #endif
779    }
780    else if ( NEXUS_AudioOutput_P_IsSpdifSlave(slaveHandle) )
781    {
782        #if NEXUS_NUM_AUDIO_RETURN_CHANNEL
783            NEXUS_Error errCode;
784   
785            errCode = NEXUS_AudioReturnChannel_P_SetMaster( slaveHandle, sourceHandle );
786               
787            if ( errCode )
788            {
789                return BERR_TRACE(errCode);
790            }       
791        #endif
792    }
793
794    return BERR_SUCCESS;
795}
796
797NEXUS_AudioOutputData *NEXUS_AudioOutput_P_CreateData(NEXUS_AudioOutput output)
798{
799    NEXUS_AudioOutputData *pData;
800    if ( NULL == output->pMixerData )
801    {
802        output->pMixerData = pData = BKNI_Malloc(sizeof(NEXUS_AudioOutputData));
803        if ( pData )
804        {
805            BKNI_Memset(pData, 0, sizeof(NEXUS_AudioOutputData));
806            BDBG_OBJECT_SET(pData, NEXUS_AudioOutputData);
807            NEXUS_AudioOutput_GetDefaultSettings( &pData->settings);
808            pData->sampleRate = BAVC_AudioSamplingRate_eUnknown;
809            switch ( output->objectType )
810            {
811            #if NEXUS_NUM_HDMI_OUTPUTS  /* TODO */
812            case NEXUS_AudioOutputType_eHdmi:
813                #if NEXUS_NUM_HDMI_OUTPUTS != 1
814                #error More than one HDMI output is not supported
815                #endif
816                BDBG_ASSERT(g_hdmiMapping[0].output == NULL);
817                {
818                    BERR_Code errCode;
819                    BAPE_OutputPort mixerOutput;
820                    BAPE_MaiOutputInterruptHandlers interrupts;
821
822                    BDBG_MSG(("Creating MAI handle"));
823                    errCode = BAPE_MaiOutput_Open(NEXUS_AUDIO_DEVICE_HANDLE, 0, NULL, &g_hdmiMapping[0].handle);
824                    if ( errCode )
825                    {
826                        BDBG_ERR(("Unable to open MAI Output"));
827                        BKNI_Free(output->pMixerData);
828                        output->pMixerData = NULL;
829                        return NULL;
830                    }
831
832                    errCode = BKNI_CreateEvent(&g_hdmiMapping[0].settingsChangedEvent);
833                    if ( errCode )
834                    {
835                        errCode = BERR_TRACE(errCode);
836                        BAPE_MaiOutput_Close(g_hdmiMapping[0].handle);
837                        BKNI_Free(output->pMixerData);
838                        output->pMixerData = NULL;
839                        return NULL;
840                    }
841
842                    g_hdmiMapping[0].settingsChangedCallback = NEXUS_RegisterEvent(g_hdmiMapping[0].settingsChangedEvent, NEXUS_AudioOutput_P_HdmiSettingsChanged, output);
843                    if ( NULL == g_hdmiMapping[0].settingsChangedCallback )
844                    {
845                        errCode = BERR_TRACE(errCode);
846                        BKNI_DestroyEvent(g_hdmiMapping[0].settingsChangedEvent);
847                        BAPE_MaiOutput_Close(g_hdmiMapping[0].handle);
848                        BKNI_Free(output->pMixerData);
849                        output->pMixerData = NULL;
850                        return NULL;
851                    }
852
853                    BAPE_MaiOutput_GetInterruptHandlers(g_hdmiMapping[0].handle, &interrupts);
854                    interrupts.sampleRate.pCallback_isr = NEXUS_AudioOutput_P_HdmiSampleRateChange_isr;
855                    interrupts.sampleRate.pParam1 = output->pObjectHandle;
856                    interrupts.sampleRate.param2 = (int)output;
857                    errCode = BAPE_MaiOutput_SetInterruptHandlers(g_hdmiMapping[0].handle, &interrupts);
858                    if ( errCode )
859                    {
860                        BDBG_ERR(("Unable to register sample rate interrupt"));
861                        NEXUS_UnregisterEvent(g_hdmiMapping[0].settingsChangedCallback);
862                        BKNI_DestroyEvent(g_hdmiMapping[0].settingsChangedEvent);
863                        BAPE_MaiOutput_Close(g_hdmiMapping[0].handle);
864                        BKNI_Free(output->pMixerData);
865                        output->pMixerData = NULL;
866                        return NULL;
867                    }                   
868                    g_hdmiMapping[0].output = output;
869                    BAPE_MaiOutput_GetOutputPort(g_hdmiMapping[0].handle, &mixerOutput);
870                    output->port = (uint32_t)mixerOutput;
871
872                    NEXUS_Module_Lock(g_NEXUS_audioModuleData.settings.modules.hdmiOutput);
873                    NEXUS_HdmiOutput_SetNotifyAudioEvent_priv(output->pObjectHandle, g_hdmiMapping[0].settingsChangedEvent);
874                    NEXUS_Module_Unlock(g_NEXUS_audioModuleData.settings.modules.hdmiOutput);
875                }
876                break;
877            #endif
878            #if NEXUS_NUM_RFM_OUTPUTS
879            case NEXUS_AudioOutputType_eRfm:
880                #if NEXUS_NUM_RFM_OUTPUTS != 1
881                #error More than one RFM output is not supported
882                #endif
883                BDBG_ASSERT(g_rfmMapping[0].output == NULL);
884                {
885                    BERR_Code errCode;
886                    BDBG_MSG(("Creating RFM handle"));
887                    errCode = BAPE_RfMod_Open(NEXUS_AUDIO_DEVICE_HANDLE, 0, NULL, &g_rfmMapping[0].handle);
888                    if ( errCode )
889                    {
890                        BDBG_ERR(("Unable to open MAI Output"));
891                        BKNI_Free(output->pMixerData);
892                        output->pMixerData = NULL;
893                        return NULL;
894                    }
895                    g_rfmMapping[0].output = output;
896                    output->port = 0;
897                }
898                break;
899            #endif
900            default:
901                break;
902            }
903        }
904        else
905        {
906            NEXUS_Error errCode;
907            errCode = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
908            return NULL;
909        }
910    }
911
912    return output->pMixerData;
913}
914
915void NEXUS_AudioOutput_GetSyncSettings_priv( NEXUS_AudioOutput audioOutput, NEXUS_AudioOutputSyncSettings *pSyncSettings )
916{
917    NEXUS_AudioOutputData *pData = audioOutput->pMixerData;
918    NEXUS_ASSERT_MODULE();
919    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
920    *pSyncSettings = pData->syncSettings;
921}
922
923NEXUS_Error NEXUS_AudioOutput_SetSyncSettings_priv( NEXUS_AudioOutput audioOutput, const NEXUS_AudioOutputSyncSettings *pSyncSettings )
924{
925    NEXUS_AudioOutputData *pData = audioOutput->pMixerData;
926
927    NEXUS_ASSERT_MODULE();
928    if (!pData) return 0; /* TODO */
929
930    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
931    pData->syncSettings = *pSyncSettings;
932
933    BKNI_EnterCriticalSection();
934    /* fire right away. always "on". */
935    if (pSyncSettings->startCallback_isr) {
936        (*pSyncSettings->startCallback_isr)(pSyncSettings->callbackContext, 0);
937    }
938    BKNI_LeaveCriticalSection();
939
940    /* set delay + additionalDelay */
941    if ( !g_NEXUS_audioModuleData.settings.independentDelay && 
942         (pData->settings.additionalDelay || pData->syncSettings.delay) )
943    {
944        BDBG_ERR(("Independent output delay is not enabled, ignoring delay.  Please check NEXUS_AudioModuleSettings.independentDelay"));
945        return BERR_TRACE(BERR_INVALID_PARAMETER);
946    }
947
948    /* Applying remaining settings should be deferred until the next start call if we're running. */
949    if ( pData->input )
950    {
951        NEXUS_AudioInput_P_OutputSettingsChanged(pData->input, audioOutput);
952    }
953
954    return NEXUS_SUCCESS;
955}
956
957NEXUS_Error NEXUS_AudioOutput_GetSyncStatus_isr( NEXUS_AudioOutput audioOutput, NEXUS_AudioOutputSyncStatus *pSyncStatus )
958{
959
960    BDBG_ASSERT(NULL != audioOutput);
961    BDBG_ASSERT(NULL != pSyncStatus);
962
963    /* Default to PCM */
964    pSyncStatus->compressed = false;
965
966    /* Look for connected input.  If found, determine format from AudioInput. */
967    if ( NULL != audioOutput->pMixerData )
968    {
969        NEXUS_AudioOutputData *pData;
970
971        pData = audioOutput->pMixerData;
972        BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
973        if ( pData->input != NULL )
974        {
975            NEXUS_AudioInputFormat format = NEXUS_AudioInput_P_GetFormat(pData->input);
976
977            if ( format == NEXUS_AudioInputFormat_eCompressed )
978            {
979                pSyncStatus->compressed = true;
980            }
981        }
982    }
983
984    return NEXUS_SUCCESS;
985}
986
987NEXUS_Error NEXUS_AudioOutput_GetStatus( NEXUS_AudioOutput audioOutput, NEXUS_AudioOutputStatus *pStatus )
988{
989    NEXUS_AudioOutputData *pData = audioOutput->pMixerData;
990    if (!pData) {
991        BKNI_Memset(pStatus, 0, sizeof(*pStatus));
992    }
993    else {
994        BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
995        *pStatus = pData->status;
996    }
997    return 0;
998}
999
1000void NEXUS_AudioOutput_P_SetVcxo(
1001    unsigned outputTimebase
1002    )
1003{
1004#if 0 /* TODO */
1005    uint32_t reg;
1006    BREG_Handle hRegister = g_pCoreHandles->reg;
1007
1008    /* Hack since we lack a PI for setting Vcxo */
1009    /* set the VCXO Timebase for Rate Manager 0 */
1010    /* TODO: what about chips w/ 2nd Rate Managers, do we need to use its VCXO */
1011    BKNI_EnterCriticalSection();
1012    reg = BREG_Read32(hRegister, BCHP_VCXO_0_RM_CONTROL);
1013    reg &= ~(BCHP_MASK(VCXO_0_RM_CONTROL,TIMEBASE));
1014    reg |= BCHP_FIELD_DATA(VCXO_0_RM_CONTROL,TIMEBASE, outputTimebase);
1015    BREG_Write32(hRegister, BCHP_VCXO_0_RM_CONTROL, reg);
1016    BKNI_LeaveCriticalSection();
1017    BDBG_MSG(("%s: Set Rate Manager 0's VCXO to sync with Timebase %d", __FUNCTION__, outputTimebase));
1018#else
1019    BSTD_UNUSED(outputTimebase);
1020#endif
1021}
1022
1023#if 0 /* TODO */
1024NEXUS_Error NEXUS_AudioOutput_P_SetHbrMode(
1025    NEXUS_AudioOutput output,
1026    bool bEnableHbr
1027    )
1028{
1029    NEXUS_Error errCode;
1030
1031    BRAP_OutputPortConfig outputSettings;
1032    BDBG_ASSERT(NULL != output);
1033
1034    if ( output->objectType == NEXUS_AudioOutputType_eHdmi ||
1035         output->objectType == NEXUS_AudioOutputType_eSpdif )
1036    {
1037        errCode = BRAP_GetCurrentOutputConfig(g_NEXUS_audioModuleData.hRap,
1038                                              output->port,
1039                                              &outputSettings);
1040        if ( errCode )
1041        {
1042            return BERR_TRACE(errCode);
1043        }
1044
1045        outputSettings.bHbrEnable = bEnableHbr;
1046
1047        errCode = BRAP_SetOutputConfig(g_NEXUS_audioModuleData.hRap,
1048                                       &outputSettings);
1049        if ( errCode )
1050        {
1051            return BERR_TRACE(errCode);
1052        }
1053    }
1054    else if ( bEnableHbr )
1055    {
1056        BDBG_ERR(("Can not enable HBR mode for outputs other than HDMI or SPDIF."));
1057        return BERR_TRACE(BERR_NOT_SUPPORTED);
1058    }
1059
1060    return BERR_SUCCESS;
1061}
1062#endif
1063
1064NEXUS_Error NEXUS_AudioOutput_P_SetTrickMute(
1065    NEXUS_AudioOutput output,
1066    bool mute
1067    )
1068{
1069    BAPE_OutputVolume volume;
1070    NEXUS_AudioOutputData *pData;
1071    NEXUS_Error errCode;
1072
1073    if ( NEXUS_AudioOutput_P_IsDacSlave(output) ||
1074         NEXUS_AudioOutput_P_IsSpdifSlave(output) )
1075    {
1076        return NEXUS_SUCCESS;
1077    }
1078
1079    if ( NULL == output->pMixerData )
1080    {
1081        pData = NEXUS_AudioOutput_P_CreateData(output);
1082        if ( NULL == pData )
1083        {
1084            return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
1085        }
1086    }
1087
1088    pData = output->pMixerData;
1089    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
1090
1091    BDBG_MSG(("Setting output mute to %d for trick", pData->settings.muted || mute));
1092    BAPE_GetOutputVolume((BAPE_OutputPort)output->port, &volume);
1093    volume.muted = pData->settings.muted || mute;
1094    errCode = BAPE_SetOutputVolume((BAPE_OutputPort)output->port, &volume);
1095    if ( errCode )
1096    {
1097        return BERR_TRACE(errCode);
1098    }
1099
1100    pData->trickMute = mute;
1101    return NEXUS_SUCCESS;
1102}
1103
1104/***************************************************************************
1105Summary:
1106    Determine if an output is connected to any inputs
1107 ***************************************************************************/
1108bool NEXUS_AudioOutput_P_IsConnected(
1109    NEXUS_AudioOutput output
1110    )
1111{
1112    NEXUS_AudioOutputData *pData;
1113
1114    BDBG_ASSERT(NULL != output);
1115
1116    pData = output->pMixerData;
1117    if ( NULL != pData && NULL != pData->input )
1118    {
1119        BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
1120        return true;
1121    }
1122
1123    return false;
1124}
1125
1126#if NEXUS_NUM_HDMI_OUTPUTS
1127static void NEXUS_AudioOutput_P_HdmiSampleRateChange_isr(void *pParam1, int param2, unsigned sampleRate)
1128{
1129    BAVC_AudioSamplingRate avcRate;
1130    NEXUS_AudioOutput output;
1131    NEXUS_AudioOutputData *pData;
1132
1133    BSTD_UNUSED(pParam1);
1134
1135    BDBG_MSG(("HDMI Sample Rate Change %u", sampleRate));
1136
1137    avcRate = NEXUS_AudioOutput_P_GetSampleRateEnum_isr(sampleRate);
1138    output=(NEXUS_AudioOutput)param2;
1139    pData = output->pMixerData;
1140    BDBG_ASSERT(NULL != pData);
1141    pData->sampleRate = avcRate;
1142
1143    NEXUS_HdmiOutput_AudioSampleRateChange_isr(output->pObjectHandle, avcRate);
1144}
1145
1146static void NEXUS_AudioOutput_P_HdmiSettingsChanged(void *pOutput)
1147{
1148    NEXUS_AudioOutput output = (NEXUS_AudioOutput)pOutput;
1149    NEXUS_AudioOutputSettings outputSettings;
1150
1151    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
1152    BDBG_ASSERT(output->objectType == NEXUS_AudioOutputType_eHdmi);
1153   
1154    BDBG_MSG(("HDMI audio settings have changed.  Updating."));
1155
1156    /* this will force the settings to be applied to the PI */
1157    NEXUS_AudioOutput_GetSettings(output, &outputSettings);
1158    NEXUS_AudioOutput_SetSettings(output, &outputSettings);
1159}
1160#endif
1161
1162void NEXUS_AudioOutput_P_GetMixerSettings(NEXUS_AudioOutput output, BAPE_MixerSettings *pSettings /* [out] */)
1163{
1164    NEXUS_AudioOutputData *pData;
1165    BDBG_ASSERT(NULL != output);
1166    pData = output->pMixerData;
1167    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
1168    BAPE_Mixer_GetDefaultSettings(pSettings);
1169    pSettings->defaultSampleRate = pData->settings.defaultSampleRate;
1170    pSettings->outputPll = pData->settings.pll;
1171    pSettings->outputNco = pData->settings.nco;
1172    pSettings->outputTimebase = pData->settings.timebase;
1173    pSettings->outputDelay = pData->settings.additionalDelay;
1174}
1175
1176void NEXUS_AudioOutput_P_SetOutputFormat(NEXUS_AudioOutput output, NEXUS_AudioInputFormat format)
1177{
1178    BDBG_ASSERT(NULL != output);
1179#if NEXUS_NUM_HDMI_OUTPUTS
1180    if ( output->objectType == NEXUS_AudioOutputType_eHdmi )
1181    {
1182        NEXUS_Module_Lock(g_NEXUS_audioModuleData.settings.modules.hdmiOutput);
1183        {
1184            BAVC_AudioSamplingRate sampleRate = BAVC_AudioSamplingRate_e48k;
1185            NEXUS_AudioOutputData *pData = output->pMixerData;
1186            unsigned numberOfChannels = format == NEXUS_AudioInputFormat_ePcm5_1?6:2;
1187            if ( pData )
1188            {
1189                if ( pData->sampleRate == BAVC_AudioSamplingRate_eUnknown )
1190                {
1191                sampleRate = NEXUS_AudioOutput_P_GetSampleRateEnum(pData->settings.defaultSampleRate);
1192                }
1193                else
1194                {
1195                    sampleRate = pData->sampleRate;
1196                }
1197            }
1198            /* Eventually, audio decoder will need to set the proper compressed format */
1199            NEXUS_HdmiOutput_SetAudioParams_priv(output->pObjectHandle, BAVC_AudioBits_e16, sampleRate,
1200                                                 format == NEXUS_AudioInputFormat_eCompressed?BAVC_AudioFormat_eAC3:BAVC_AudioFormat_ePCM,numberOfChannels);
1201        }
1202        NEXUS_Module_Unlock(g_NEXUS_audioModuleData.settings.modules.hdmiOutput);
1203    }
1204#else
1205    BSTD_UNUSED(output);
1206    BSTD_UNUSED(format);
1207#endif
1208}
1209
1210bool NEXUS_AudioOutput_P_IsRunning(
1211    NEXUS_AudioOutput output
1212    )
1213{
1214    NEXUS_AudioOutputData *pData;
1215   
1216    BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput);
1217   
1218    pData = output->pMixerData;
1219    if ( NULL == pData )
1220    {
1221        /* No connection can have been made, so we can't be running */
1222        return false;
1223    }
1224    BDBG_OBJECT_ASSERT(pData, NEXUS_AudioOutputData);
1225    if ( NULL == pData->input )
1226    {
1227        /* There is no input, can't be running */
1228        return false;
1229    }
1230   
1231    /* We're running if our input is running. */
1232    return NEXUS_AudioInput_P_IsRunning(pData->input);
1233}
Note: See TracBrowser for help on using the repository browser.