source: svn/newcon3bcm2_21bu/nexus/modules/transport/7552/src/nexus_timebase.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: 41.9 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_timebase.c $
39* $brcm_Revision: 61 $
40* $brcm_Date: 12/9/11 5:22p $
41*
42* API Description:
43*   Management of timebase (clock rate) blocks.
44*
45* Revision History:
46*
47* $brcm_Log: /nexus/modules/transport/7400/src/nexus_timebase.c $
48*
49* 61   12/9/11 5:22p bandrews
50* SW7550-772: merge to main
51*
52* SW7550-772/1   12/8/11 8:58p bandrews
53* SW7550-772: implement default timebase usage
54*
55* 60   11/14/11 2:28p erickson
56* SW7425-1448: add NEXUS_Timebase_SetVdecFrameRate and
57*  NEXUS_Timebase_SetHdDviFrameRate
58*
59* 59   11/7/11 4:00p bandrews
60* SW7231-446: merge to main
61*
62* SW7231-446/1   11/4/11 10:11p bandrews
63* SW7231-446: updates for kernel mode
64*
65* 58   10/31/11 7:48p bandrews
66* SW7231-391: merge to main
67*
68* SW7420-2078/5   10/25/11 7:26p bandrews
69* SW7231-391: fix warnings
70*
71* SW7420-2078/4   10/25/11 5:22p bandrews
72* SW7231-391: update parser band and timebase implementations to use
73*  handles everywhere, even for legacy enum usage
74*
75* SW7420-2078/3   10/14/11 8:36p bandrews
76* SW7231-391: update stc channel to work with client timebase
77*
78* SW7420-2078/2   10/14/11 5:05p bandrews
79* SW7231-391: timebase must be > eMax to check in objdb
80*
81* SW7420-2078/1   10/11/11 8:26p bandrews
82* SW7231-391: add support for parser band and timebase protected client
83*  usage
84*
85* 57   9/14/11 2:00p erickson
86* SW7408-284: add
87*  NEXUS_TimebaseSettings.sourceSettings.pcr.jitterCorrection
88*
89* 56   5/11/11 3:50p akam
90* SWDTV-7071: Merged SWDTV-5829 to main line.
91*
92* SWDTV-5829/6   5/11/11 11:58a akam
93* SWDTV-5829: Merged from main.
94*
95* SWDTV-5829/5   3/30/11 10:43a petlee
96* SWDTV-5829: Update calculation of inc and center freq again for
97*  24/25/30/50/60 Hz
98*
99* SWDTV-5829/4   3/29/11 4:46p petlee
100* SWDTV-5829: Update calculation of inc and center freq
101*
102* SWDTV-5829/3   3/28/11 9:53a rgreen
103* SWDTV-5829: Update vdec and hddvi to also use video format to determine
104*  inc and center freq
105*
106* SWDTV-5829/2   3/21/11 5:13p petlee
107* SWDTV-5829: Update vdec and hddvi to also use video format to determine
108*  inc and center freq
109*
110* SWDTV-5829/1   3/18/11 5:40p petlee
111* Update Nexus to sync output frequency to input using hddvi vsync clock
112*
113* 54   11/19/10 11:01a jtna
114* SW7408-181: merge
115*
116* 53   11/8/10 4:04p gmullen
117* SW7422-20: Use Int IDs generated by BXPT
118*
119* 52   10/28/10 5:09p erickson
120* SW7422-20: adapt to new XPT PI (backward compat using magnum and nexus
121*  macros)
122*
123* 51   9/20/10 1:33p petlee
124* SW35230-1156: Update vdec index for 35230
125*
126* 50   7/21/10 4:42p jhaberf
127* SW35230-694: changes for analog video PIP
128*
129* 49   7/14/10 5:37p erickson
130* SW3556-1145: add NEXUS_TimebaseTrackRange to all source type settings
131*
132* 48   5/3/10 11:15a erickson
133* SW7335-706: add NEXUS_TimebaseStatus.lastValueLo
134*
135* 47   12/11/09 6:41p mphillip
136* SW7550-112: Merge 7550 changes to main branch
137*
138* 46   12/1/09 6:30p randyjew
139* SW7468-6: Add 7468 support
140*
141* 45   11/19/09 4:25p gmohile
142* SW7408-1 : Add 7408 support
143*
144* 44   9/18/09 10:53a jhaberf
145* SW35230-1: Added support for the 35230 DTV chip
146*
147* 43   8/24/09 3:03p jrubio
148* SW7342-11: add timebase protection for DPCR1
149*
150* 42   8/19/09 4:04p mward
151* PR55545: Support for 7125.
152*
153* 41   8/5/09 4:56p jrubio
154* PR55232: add 7342/7340 support
155*
156* 40   7/17/09 7:13p bandrews
157* PR49215: astm dvr support
158*
159* 39   6/25/09 11:16a erickson
160* PR46889: change pcrError from MSG to WRN. this WRN will only print if
161*  NEXUS_TimebaseSettings.pcrErrorCallback is set.
162*
163* 38   6/12/09 5:58p bandrews
164* PR52472: Use phase error instead of computing PCR - STC directly
165*
166* 37   4/28/09 10:29a erickson
167* PR54656: call BXPT_PCR_DirecTv_GetLastPcr in DSS mode
168*
169* 36   1/20/09 4:59p bandrews
170* PR51021: Change warning to message
171*
172* 35   1/19/09 5:28p bandrews
173* PR51021: merge
174*
175* PR51021/2   1/16/09 4:13p bandrews
176* PR51021: Updated to separate permission from enable
177*
178* PR51021/1   1/16/09 12:18a bandrews
179* PR51021: First stab at cleaning up ASTM playback blockage
180*
181* 34   12/19/08 10:15a jgarrett
182* PR 49587: Fixing loop filter values to appropriate values by default
183*
184* 33   12/9/08 6:32p nickh
185* PR48963: Fix compile errors for 7420 PCR changes
186*
187* 32   12/8/08 3:01p bandrews
188* PR50016: ensure that even if playback is set before start ASTM we
189*  default dependencies
190*
191* 31   12/3/08 3:18p nickh
192* PR48963: Add support for 7420 PCR hardware which uses a PID channel as
193*  opposed to PID value
194*
195* 30   12/2/08 3:14p jgarrett
196* PR 49587: Merging to mainline
197*
198* Nexus_Devel/wince_7400/9   9/17/08 5:29p ptimariu
199* PR47063: merge from nexus 3.2 mainline
200*
201* 29   11/24/08 11:45a erickson
202* PR48846: move pcrErrorCallback outside substruct for kernel mode proxy
203*  parsing
204*
205* 28   11/24/08 10:28a erickson
206* PR48846: added pcrError callback
207*
208* 27   11/21/08 1:21p erickson
209* PR49212: NEXUS_Timebase_SetSettings needs to be able to compare new
210*  with current settings. added "force" option for sourceType changes.
211*  preserved Astm logic for overriding sourceType in
212*  NEXUS_Timebase_SetSettings.
213*
214* 26   11/18/08 9:38p bandrews
215* PR49212: Corrected logic error for disabling ASTM settings during
216*  playback
217*
218* 25   11/18/08 8:53p bandrews
219* PR49212: Temporarily block ASTM during playback
220*
221* 24   11/18/08 7:45p bandrews
222* PR49212: ASTM overrides user settings, but it should not destroy them
223*  when it does so
224*
225* 23   10/24/08 4:42p erickson
226* PR47232: added trackRange for freeRun
227*
228* 22   10/7/08 10:40p erickson
229* PR47232: move centerFrequency to freeRun.centerFrequency'
230*
231* 21   10/6/08 2:35a erickson
232* PR47232: added
233*  NEXUS_TimebaseSettings.sourceSettings.pcr.centerFrequency
234*
235* 20   9/3/08 7:34p vishk
236* PR 46315: Sample code for PID remapping
237*
238* 19   9/2/08 11:19a erickson
239* PR46213: added NEXUS_TimebaseSettings.freeze
240*
241* 18   7/17/08 10:45a erickson
242* PR44492: add NEXUS_TimebaseSettings.sourceSettings.i2s.sampleRate
243*
244* 17   7/14/08 12:04p erickson
245* PR42739: added options for IPTV
246*
247* PR42739/1   7/10/08 10:26p ssood
248* PR42739: Adding support to absorb high jitter for Live IP Channels
249*
250* 16   7/3/08 10:40a erickson
251* PR44492: add i2s and spdif timebase selection
252*
253* 15   6/23/08 3:16p jgarrett
254* PR 43995: Fixing astm monitor callbacks
255*
256* 14   5/1/08 2:55p erickson
257* PR42391: remove duplicate and unused storage to prevent future bugs
258*
259* 13   4/28/08 11:53a erickson
260* PR42197: remove NEXUS_ParserBand_ePlayback enums
261*
262* 12   4/8/08 1:53p erickson
263* PR39453: add 3548 & 3556
264*
265* 11   4/1/08 3:11p erickson
266* PR40716: move break out of #if B_HAS_DSS
267*
268* 10   3/31/08 2:01p erickson
269* PR40421: allow callback Set with NULL to clear callback
270*
271***************************************************************************/
272#include "nexus_transport_module.h"
273#include "nexus_class_verification.h"
274
275#define NEXUS_TIMEBASE_PCR_CLOCK    0x337f980 /* may be chip-dependent */
276#define NEXUS_TIMEBASE_HDDVI_CLOCK  0xcdfe600 /* may be chip-depenedent */
277#define NEXUS_TIMEBASE_FREQ_FACTOR  1000
278
279BDBG_MODULE(nexus_timebase);
280
281static NEXUS_Error NEXUS_Timebase_P_SetTwoPcrErrorMonitor(NEXUS_TimebaseHandle timebase, bool forceOff);
282
283NEXUS_TimebaseHandle NEXUS_Timebase_Resolve_priv(NEXUS_Timebase timebase)
284{
285    NEXUS_TimebaseHandle out = NULL;
286   
287    NEXUS_ASSERT_MODULE();
288
289    if (timebase != NEXUS_Timebase_eInvalid)
290    {
291        if ((unsigned)timebase < (unsigned)NEXUS_Timebase_eMax)
292        {
293            unsigned index = timebase - NEXUS_Timebase_e0; /* assumes continuous enums */
294           
295            if (index < NEXUS_NUM_TIMEBASES)
296            {
297                /* enum variant */
298#if BDBG_DEBUG_BUILD
299                if (!pTransport->timebase[index].acquired)
300                {
301                    BDBG_MSG(("Allocating timebase %u to unprotected client", index));
302                }
303#endif
304                pTransport->timebase[index].acquired = true;
305                out = &pTransport->timebase[index];
306            }
307            else
308            {
309                BERR_TRACE(NEXUS_INVALID_PARAMETER);
310            }
311        }
312        else if ((unsigned)timebase > (unsigned)NEXUS_Timebase_eMax)
313        {
314            /* pointer variant */
315            out = (NEXUS_TimebaseHandle)timebase;
316            BDBG_OBJECT_ASSERT(out, NEXUS_TimebaseImpl);
317        }
318        else /*if (timebase == NEXUS_Timebase_eMax)*/
319        {
320            BERR_TRACE(NEXUS_INVALID_PARAMETER);
321        }
322    }
323    else
324    {
325        /* eInvalid means use the default timebase, which is e0, but don't acquire it */
326        out = &pTransport->timebase[0];
327    }
328
329    return out;
330}
331
332void NEXUS_Timebase_GetDefaultSettings_priv(NEXUS_TimebaseSettings *pSettings)
333{
334    BXPT_PCR_TimebaseFreqRefConfig freqRefCfg;
335    BERR_Code rc;
336
337    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
338    pSettings->sourceType = NEXUS_TimebaseSourceType_eFreeRun;
339    pSettings->sourceSettings.pcr.maxPcrError = 0xFF;
340    pSettings->sourceSettings.pcr.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
341    pSettings->sourceSettings.pcr.jitterCorrection = NEXUS_TristateEnable_eNotSet; /* this is "auto". the current HW implementation of DPCR jitter correction is a
342        global setting. so, if we default to auto, then any one timebase that sets it will enable it system-wide. */
343    pSettings->sourceSettings.freeRun.centerFrequency = 0x400000;
344    pSettings->sourceSettings.freeRun.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
345    pSettings->sourceSettings.vdec.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
346    pSettings->sourceSettings.hdDvi.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
347    pSettings->sourceSettings.ccir656.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
348    pSettings->sourceSettings.i2s.trackRange = NEXUS_TimebaseTrackRange_e61ppm;
349
350    /* at init time, consult HW settings so that, by default, there is no change */
351    /* hard code to use timebase zero, because we don't really need an actual timebase for this call */
352    rc = BXPT_PCR_GetTimeBaseFreqRefDefaults(pTransport->timebase[0].pcr, BXPT_PCR_TimeRef_eInternal, &freqRefCfg);
353    if (rc) {
354        rc=BERR_TRACE(rc);
355    }
356    else {
357        /* make SW state == HW state */
358        pSettings->sourceSettings.freeRun.prescale = freqRefCfg.Prescale;
359        pSettings->sourceSettings.freeRun.inc = freqRefCfg.Inc;
360        pSettings->sourceSettings.freeRun.loopDirectPathGain = freqRefCfg.FiltA;
361        pSettings->sourceSettings.freeRun.loopGain = freqRefCfg.FiltB;
362        pSettings->sourceSettings.freeRun.loopIntegratorLeak = freqRefCfg.FiltC;
363    }
364}
365
366/* 108MHz VDEC clock. */
367NEXUS_Error NEXUS_Timebase_P_GetDpcrCoefficients(NEXUS_VideoFrameRate frameRate, unsigned *inc, unsigned *prescale)
368{
369    /* select clock coefficient, based on the source format */
370    switch (frameRate) {
371    case NEXUS_VideoFrameRate_e29_97:
372    case NEXUS_VideoFrameRate_e59_94:
373        *inc = 900900;
374        break;
375    case NEXUS_VideoFrameRate_e30:
376    case NEXUS_VideoFrameRate_e60:
377        *inc = 900000;
378        break;
379    case NEXUS_VideoFrameRate_e25:
380    case NEXUS_VideoFrameRate_e50:
381        *inc = 1080000;
382        break;
383    case NEXUS_VideoFrameRate_e23_976:
384        *inc = 2252250;
385        break;
386    case NEXUS_VideoFrameRate_e24:
387        *inc = 2250000;
388        break;
389    case NEXUS_VideoFrameRate_eUnknown:
390        /* leave unchanged */
391        break;
392    default:
393        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
394    }
395    *prescale = 0;
396    return 0;
397}
398
399NEXUS_Error NEXUS_Timebase_P_GetDpcrCoefficientsFromVideoFormat(NEXUS_VideoFormat videoFormat, NEXUS_VideoFrameRate frameRate, unsigned *inc, unsigned *prescale)
400{
401    NEXUS_VideoFormatInfo videoFmtInfo;
402    uint32_t refreshRate; /* this is the refresh rate multiplied by a factor of 1000 */
403
404    if (NEXUS_VideoFormat_eUnknown == videoFormat)
405    {
406        return NEXUS_Timebase_P_GetDpcrCoefficients(frameRate, inc, prescale);
407    }
408
409    NEXUS_VideoFormat_GetInfo(videoFormat, &videoFmtInfo);
410
411    refreshRate = (2397 == videoFmtInfo.verticalFreq) ? 23976 : videoFmtInfo.verticalFreq * 10;
412    *inc = (uint32_t)((uint64_t)NEXUS_TIMEBASE_PCR_CLOCK * (uint64_t)NEXUS_TIMEBASE_FREQ_FACTOR / (uint64_t)refreshRate);
413    *prescale = 0;
414
415    return NEXUS_SUCCESS;
416}
417
418NEXUS_Error NEXUS_Timebase_P_GetIncAndCenterFreq(NEXUS_VideoFormat videoFormat, unsigned vertSyncClock, unsigned *inc, unsigned *centerFreq)
419{
420    NEXUS_VideoFormatInfo videoFmtInfo;
421    uint32_t refreshRate = 0;
422    uint32_t hddviFactor = 0;
423    uint32_t pcrFactor = 0;
424
425    if (0 == vertSyncClock || NEXUS_VideoFormat_eUnknown == videoFormat) return BERR_TRACE(NEXUS_INVALID_PARAMETER);
426
427    NEXUS_VideoFormat_GetInfo(videoFormat, &videoFmtInfo);
428
429    if ((2300 < videoFmtInfo.verticalFreq) && (2450 >= videoFmtInfo.verticalFreq)) {
430        refreshRate = 24;
431    } else if ((2450 < videoFmtInfo.verticalFreq) && (2600 >= videoFmtInfo.verticalFreq)) {
432        refreshRate = 25;
433    } else if ((2900 < videoFmtInfo.verticalFreq) && (3100 >= videoFmtInfo.verticalFreq)) {
434        refreshRate = 30 ;
435    } else if ((4900 < videoFmtInfo.verticalFreq) && (5100 >= videoFmtInfo.verticalFreq)) {
436        refreshRate = 50;
437    } else if ((5900 < videoFmtInfo.verticalFreq) && (6100 >= videoFmtInfo.verticalFreq)) {
438        refreshRate = 60;
439    } else {
440        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
441    }
442
443    hddviFactor = NEXUS_TIMEBASE_HDDVI_CLOCK / refreshRate;
444    pcrFactor = NEXUS_TIMEBASE_PCR_CLOCK / refreshRate;
445
446    *inc = (uint32_t)((uint64_t)pcrFactor * (uint64_t)vertSyncClock / (uint64_t)hddviFactor);
447    *centerFreq = (uint32_t)((uint64_t)0x400000 * (uint64_t)hddviFactor / (uint64_t)vertSyncClock);
448
449    BDBG_MSG(("NEXUS_Timebase_P_GetIncAndCenterFreq: refreshRate=%u, vertSyncClock=%u, inc=%u, centerFreq=%u",
450        refreshRate,
451        vertSyncClock,
452        *inc,
453        *centerFreq
454        ));
455
456
457    return NEXUS_SUCCESS;
458}
459
460NEXUS_Error NEXUS_Timebase_P_SetSettings(NEXUS_TimebaseHandle timebase, const NEXUS_TimebaseSettings *pSettings)
461{
462    BERR_Code rc;
463    BXPT_PCR_Handle pcr = NULL;
464    BXPT_PCR_TimebaseFreqRefConfig freqRefConfig;
465    BXPT_PCR_TimeRef timeref;
466    NEXUS_TimebaseSourceType sourceType;
467#if NEXUS_HAS_ASTM
468    NEXUS_TimebaseAstmSettings * pAstmSettings;
469#endif
470    bool force;
471
472    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
473   
474    pcr = timebase->pcr;
475    /* read sourceType out of the structure because Astm might change it. do not use pSettings->sourceType later in this function. */
476    sourceType = pSettings->sourceType;
477
478#if NEXUS_HAS_ASTM
479    /* if we aren't attempting to set the source type to FreeRun from the user config, permit ASTM.
480    Having the user set the sourceType to eFreeRun is equivalent to being in playback mode, and we don't support that in ASTM
481    so disable ASTM */
482    pAstmSettings = &timebase->astm.settings;
483
484    if (pAstmSettings->enabled)
485    {
486        BDBG_MSG(("ASTM is setting the clock coupling for timebase %u to %s", timebase->hwIndex, pAstmSettings->clockCoupling == NEXUS_TimebaseClockCoupling_eInternalClock ? "internal" : "input"));
487        if (pAstmSettings->clockCoupling == NEXUS_TimebaseClockCoupling_eInternalClock)
488        {
489            sourceType = NEXUS_TimebaseSourceType_eFreeRun;
490        }
491    }
492#endif
493
494    timebase->status.sourceType = sourceType;
495
496    force = (sourceType != timebase->settings.sourceType);
497
498    if ( sourceType == NEXUS_TimebaseSourceType_ePcr) {
499        NEXUS_IsrCallback_Set(timebase->monitorCallback, &pSettings->pcrCallback);
500    }
501    else {
502        NEXUS_IsrCallback_Set(timebase->monitorCallback, NULL);
503    }
504
505    timebase->isDss = false;
506    switch (sourceType) {
507    case NEXUS_TimebaseSourceType_ePcr:
508        {
509        BXPT_PCR_XptStreamPcrCfg pcrConfig;
510#if BXPT_DPCR_GLOBAL_PACKET_PROC_CTRL
511        BXPT_PCR_JitterCorrection jitterCorrection;
512#endif
513        NEXUS_PidChannelHandle pcrPidChannel = pSettings->sourceSettings.pcr.pidChannel;
514       
515        if (!pcrPidChannel) {
516            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
517        }
518       
519        rc = BXPT_PCR_GetStreamPcrConfig(pcr, &pcrConfig);
520        if (rc) {return BERR_TRACE(rc);}
521
522#if BXPT_DPCR_GLOBAL_PACKET_PROC_CTRL
523        /* transform nexus tristate to BXPT_PCR_JitterCorrection tristate */
524        switch (pSettings->sourceSettings.pcr.jitterCorrection) {
525        case NEXUS_TristateEnable_eDisable: jitterCorrection = BXPT_PCR_JitterCorrection_eDisable; break;
526        case NEXUS_TristateEnable_eEnable:  jitterCorrection = BXPT_PCR_JitterCorrection_eEnable; break;
527        case NEXUS_TristateEnable_eNotSet:  jitterCorrection = BXPT_PCR_JitterCorrection_eAuto; break;
528        default: return BERR_TRACE(NEXUS_INVALID_PARAMETER);
529        }
530
531        if (jitterCorrection == BXPT_PCR_JitterCorrection_eAuto) {
532            pcrConfig.JitterTimestamp = BXPT_PCR_JitterTimestampMode_eAuto;
533        }
534        else if ( pcrPidChannel->status.playback ) {
535            /* for playback, nexus does not expose e28_4P or e32, so we can hardcode to e30_2U */
536            pcrConfig.JitterTimestamp = BXPT_PCR_JitterTimestampMode_e30_2U;
537        }
538        else {
539            /* for live, there is no HW capability for e30_2U or e28_4P, so we can hardcode to e32 */
540            pcrConfig.JitterTimestamp = BXPT_PCR_JitterTimestampMode_e32;
541        }
542#endif
543       
544        if ( pcrPidChannel->status.playback )
545        {
546#if !BXPT_DPCR_GLOBAL_PACKET_PROC_CTRL
547            pcrConfig.eStreamSelect = BXPT_DataSource_ePlayback;
548            pcrConfig.WhichSource = pcrPidChannel->status.playbackIndex;
549#endif
550#if BXPT_DPCR_GLOBAL_PACKET_PROC_CTRL
551            pcrConfig.PbJitterDisable = jitterCorrection;
552#endif
553        }
554        else
555        {
556            NEXUS_ParserBandSettings parserSettings;
557
558            NEXUS_ParserBand_P_GetSettings(pcrPidChannel->parserBand, &parserSettings);
559            if ( parserSettings.sourceType == NEXUS_ParserBandSourceType_eInputBand )
560            {
561#if !BXPT_DPCR_GLOBAL_PACKET_PROC_CTRL
562                pcrConfig.eStreamSelect = BXPT_DataSource_eInputBand;
563                pcrConfig.WhichSource = parserSettings.sourceTypeSettings.inputBand - NEXUS_InputBand_e0;
564#endif
565            }
566            else if ( parserSettings.sourceType == NEXUS_ParserBandSourceType_eRemux )
567            {
568                BDBG_ERR(("You cannot use a PCR pid channel from a remux looped back to a parser band. Instead, use a pid channel from the original input band."));
569                return BERR_TRACE(BERR_INVALID_PARAMETER);
570            }
571            else
572            {
573                BDBG_ERR(("Invalid parser band source (%d) for timebase input."));
574                return BERR_TRACE(BERR_INVALID_PARAMETER);
575            }
576#if BXPT_DPCR_GLOBAL_PACKET_PROC_CTRL
577            pcrConfig.LiveJitterDisable = jitterCorrection;
578#endif
579        }
580
581        pcrConfig.MaxPcrError = pSettings->sourceSettings.pcr.maxPcrError;
582#if BXPT_DPCR_GLOBAL_PACKET_PROC_CTRL
583        /* 7420 PCR hardware uses the PID channel */
584        pcrConfig.PidChannel = pcrPidChannel->status.pidChannelIndex;
585#else
586        pcrConfig.Pid = pcrPidChannel->status.pid;
587#endif
588        rc = BXPT_PCR_GetTimeBaseFreqRefDefaults(pcr, BXPT_PCR_TimeRef_eXpt, &pcrConfig.TimebaseCfg);
589        if (rc) {return BERR_TRACE(rc);}
590
591        rc = BXPT_PCR_SetStreamPcrConfig(pcr, &pcrConfig);
592        if (rc) {return BERR_TRACE(rc);}
593
594        timebase->isDss = NEXUS_IS_DSS_MODE(pcrPidChannel->status.transportType);
595
596        /* Set the crystal tracking range */
597        if (force || pSettings->sourceSettings.pcr.trackRange != timebase->settings.sourceSettings.pcr.trackRange) {
598            BDBG_CASSERT(NEXUS_TimebaseTrackRange_e244ppm == (NEXUS_TimebaseTrackRange)BXPT_PCR_TrackRange_PPM_244);
599            BXPT_PCR_SetTimeRefTrackRange(pcr, pSettings->sourceSettings.pcr.trackRange);
600        }
601
602        BDBG_MSG(("%s: PCR Mode Timebase (%u) Settings: track range %d, max pcr error %d\n",
603                    __FUNCTION__, timebase->hwIndex, pSettings->sourceSettings.pcr.trackRange, pSettings->sourceSettings.pcr.maxPcrError));
604        }
605        break;
606
607    case NEXUS_TimebaseSourceType_eFreeRun:
608        rc = BXPT_PCR_GetTimeBaseFreqRefDefaults(pcr, BXPT_PCR_TimeRef_eInternal, &freqRefConfig);
609        if (rc) {return BERR_TRACE(rc);}
610
611        freqRefConfig.FiltA = pSettings->sourceSettings.freeRun.loopDirectPathGain;
612        freqRefConfig.FiltB = pSettings->sourceSettings.freeRun.loopGain;
613        freqRefConfig.FiltC = pSettings->sourceSettings.freeRun.loopIntegratorLeak;
614
615        freqRefConfig.Prescale = pSettings->sourceSettings.freeRun.prescale;
616        freqRefConfig.Inc = pSettings->sourceSettings.freeRun.inc;
617        rc = BXPT_PCR_ConfigNonStreamTimeBase(pcr, BXPT_PCR_TimeRef_eInternal, &freqRefConfig);
618        if (rc) {return BERR_TRACE(rc);}
619
620        if (force || pSettings->sourceSettings.freeRun.centerFrequency != timebase->settings.sourceSettings.freeRun.centerFrequency) {
621            BXPT_PCR_SetCenterFrequency(pcr, pSettings->sourceSettings.freeRun.centerFrequency);
622        }
623        /* Set the crystal tracking range */
624        if (force || pSettings->sourceSettings.freeRun.trackRange != timebase->settings.sourceSettings.freeRun.trackRange) {
625            BXPT_PCR_SetTimeRefTrackRange(pcr, pSettings->sourceSettings.freeRun.trackRange);
626        }
627        break;
628
629    case NEXUS_TimebaseSourceType_eAnalog:
630        /* select clock coefficient, based on the source format */
631        /* TODO: vdec.index is needed to select the right enum here, but the user must also pass the timebase to the right NEXUS_AnalogVideoDecoder to set the right
632        framerate. This could be mismatched. */
633        switch (pSettings->sourceSettings.vdec.index) {
634#if NEXUS_DTV_PLATFORM
635#if NEXUS_DTV_PLATFORM < 3
636        case 0: timeref = BXPT_PCR_TimeRef_eVDECVl; break;
637#if NEXUS_NUM_ANALOG_VIDEO_DECODERS > 1
638        case 1: timeref = BXPT_PCR_TimeRef_eVDEC_SEC_VL; break;
639#endif
640#else
641        case 0: timeref = BXPT_PCR_TimeRef_eHD_DVI_V0; break;
642        case 1: timeref = BXPT_PCR_TimeRef_eHD_DVI_V1; break;
643#endif
644#endif
645        default: return BERR_TRACE(NEXUS_INVALID_PARAMETER);
646        }
647#if NEXUS_DTV_PLATFORM
648        rc = BXPT_PCR_GetTimeBaseFreqRefDefaults(pcr, timeref, &freqRefConfig);
649        if (rc) {return BERR_TRACE(rc);}
650
651        /* For HD VDEC's, we must look up based on various refresh rates */
652        rc = NEXUS_Timebase_P_GetDpcrCoefficientsFromVideoFormat(
653            pSettings->sourceSettings.vdec.format,
654            timebase->vdecFrameRate?timebase->vdecFrameRate:pSettings->sourceSettings.vdec.frameRate,
655            &freqRefConfig.Inc,
656            &freqRefConfig.Prescale
657            );
658        if (rc) {return BERR_TRACE(rc);}
659
660        if (pSettings->sourceSettings.hdDvi.vertSyncClock)
661        {
662            uint32_t inc = 0;
663            uint32_t centerFreq = 0;
664
665            rc = NEXUS_Timebase_P_GetIncAndCenterFreq(
666                     pSettings->sourceSettings.vdec.format,
667                     pSettings->sourceSettings.hdDvi.vertSyncClock,
668                     &inc,
669                     &centerFreq);
670
671            if (NEXUS_SUCCESS == rc)
672            {
673                freqRefConfig.Inc = inc;
674                BXPT_PCR_SetCenterFrequency(pcr, centerFreq);
675            }
676
677            BDBG_WRN(("NEXUS_Timebase_SetSettings: eAnalog - vertSyncClock=%u, inc=%u, centerFreq=%u",
678                pSettings->sourceSettings.hdDvi.vertSyncClock,
679                freqRefConfig.Inc,
680                centerFreq));
681        }
682
683        rc = BXPT_PCR_ConfigNonStreamTimeBase(pcr, timeref, &freqRefConfig);
684        if (rc) {return BERR_TRACE(rc);}
685
686        /* Set the crystal tracking range */
687        if (force || pSettings->sourceSettings.vdec.trackRange != timebase->settings.sourceSettings.vdec.trackRange) {
688            BXPT_PCR_SetTimeRefTrackRange(pcr, pSettings->sourceSettings.vdec.trackRange);
689        }
690#endif
691        break;
692
693    case NEXUS_TimebaseSourceType_eCcir656In:
694        timeref = BXPT_PCR_TimeRef_eI656_Vl;
695        rc = BXPT_PCR_GetTimeBaseFreqRefDefaults(pcr, timeref, &freqRefConfig);
696        if (rc) {return BERR_TRACE(rc);}
697
698        /* select clock coefficient, based on the source format. This is SD only, so we don't need framerate.
699        TODO: likely these values are different for 3563/3548. */
700        switch (pSettings->sourceSettings.ccir656.format) {
701        case NEXUS_VideoFormat_eNtsc:
702        case NEXUS_VideoFormat_eNtscJapan:
703            freqRefConfig.Inc = 900900; break;
704        default: /* PAL */
705            freqRefConfig.Inc = 1080000; break;
706        }
707
708        freqRefConfig.Prescale = 0;
709        rc = BXPT_PCR_ConfigNonStreamTimeBase(pcr, timeref, &freqRefConfig);
710        if (rc) {return BERR_TRACE(rc);}
711
712        /* Set the crystal tracking range */
713        if (force || pSettings->sourceSettings.ccir656.trackRange != timebase->settings.sourceSettings.ccir656.trackRange) {
714            BXPT_PCR_SetTimeRefTrackRange(pcr, pSettings->sourceSettings.ccir656.trackRange);
715        }
716        break;
717
718#if NEXUS_NUM_I2S_INPUTS > 0
719    case NEXUS_TimebaseSourceType_eI2sIn:
720        switch (pSettings->sourceSettings.i2s.index) {
721        case 0: timeref = BXPT_PCR_TimeRef_eI2S0; break;
722#if NEXUS_NUM_I2S_INPUTS > 1
723        case 1: timeref = BXPT_PCR_TimeRef_eI2S1; break;
724#endif
725        default: return BERR_TRACE(NEXUS_INVALID_PARAMETER);
726        }
727        rc = BXPT_PCR_GetTimeBaseFreqRefDefaults(pcr, timeref, &freqRefConfig);
728        if (rc) {return BERR_TRACE(rc);}
729
730        switch (pSettings->sourceSettings.i2s.sampleRate) {
731        case 48000:
732            freqRefConfig.Prescale = 1;
733            freqRefConfig.Inc = 1125;
734            break;
735        case 44100:
736            freqRefConfig.Prescale = 48;
737            freqRefConfig.Inc = 30000;
738            break;
739        case 32000:
740            freqRefConfig.Prescale = 3;
741            freqRefConfig.Inc = 3375;
742            break;
743        default:
744            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
745        }
746
747        rc = BXPT_PCR_ConfigNonStreamTimeBase(pcr, timeref, &freqRefConfig);
748        if (rc) {return BERR_TRACE(rc);}
749
750        /* Set the crystal tracking range */
751        if (force || pSettings->sourceSettings.i2s.trackRange != timebase->settings.sourceSettings.i2s.trackRange) {
752            BXPT_PCR_SetTimeRefTrackRange(pcr, pSettings->sourceSettings.i2s.trackRange);
753        }
754        break;
755#endif
756
757#if NEXUS_NUM_SPDIF_INPUTS > 0
758    case NEXUS_TimebaseSourceType_eSpdifIn:
759        timeref = BXPT_PCR_TimeRef_eSPDIF;
760
761        rc = BXPT_PCR_GetTimeBaseFreqRefDefaults(pcr, timeref, &freqRefConfig);
762        if (rc) {return BERR_TRACE(rc);}
763
764        rc = BXPT_PCR_ConfigNonStreamTimeBase(pcr, timeref, &freqRefConfig);
765        if (rc) {return BERR_TRACE(rc);}
766        break;
767#endif
768
769#if NEXUS_NUM_HDMI_INPUTS
770    case NEXUS_TimebaseSourceType_eHdDviIn:
771        switch (pSettings->sourceSettings.hdDvi.index) {
772        case 0: timeref = BXPT_PCR_TimeRef_eHD_DVI_V0; break;
773        case 1: timeref = BXPT_PCR_TimeRef_eHD_DVI_V1; break;
774        default: return BERR_TRACE(NEXUS_INVALID_PARAMETER);
775        }
776
777        /* Set XPT timebase */
778        rc = BXPT_PCR_GetTimeBaseFreqRefDefaults(pcr, timeref, &freqRefConfig);
779        if (rc) {return BERR_TRACE(rc);}
780
781        rc = NEXUS_Timebase_P_GetDpcrCoefficientsFromVideoFormat(
782            pSettings->sourceSettings.hdDvi.format,
783            timebase->hdDviFrameRate?timebase->hdDviFrameRate:pSettings->sourceSettings.hdDvi.frameRate,
784            &freqRefConfig.Inc,
785            &freqRefConfig.Prescale
786            );
787        if (rc) {return BERR_TRACE(rc);}
788
789        if (pSettings->sourceSettings.hdDvi.vertSyncClock)
790        {
791            uint32_t inc = 0;
792            uint32_t centerFreq = 0;
793
794            rc = NEXUS_Timebase_P_GetIncAndCenterFreq(
795                     pSettings->sourceSettings.hdDvi.format,
796                     pSettings->sourceSettings.hdDvi.vertSyncClock,
797                     &inc,
798                     &centerFreq);
799
800             if (NEXUS_SUCCESS == rc)
801            {
802                freqRefConfig.Inc = inc;
803                BXPT_PCR_SetCenterFrequency(pcr, centerFreq);
804            }
805
806            BDBG_MSG(("NEXUS_Timebase_SetSettings: eHdDviIn - vertSyncClock=%u, inc=%u, centerFreq=%u",
807                pSettings->sourceSettings.hdDvi.vertSyncClock,
808                freqRefConfig.Inc,
809                centerFreq));
810        }
811
812        rc = BXPT_PCR_ConfigNonStreamTimeBase(pcr, timeref, &freqRefConfig);
813        if (rc) BERR_TRACE(rc);
814
815        /* Set the crystal tracking range */
816        if (force || pSettings->sourceSettings.hdDvi.trackRange != timebase->settings.sourceSettings.hdDvi.trackRange) {
817            BXPT_PCR_SetTimeRefTrackRange(pcr, pSettings->sourceSettings.hdDvi.trackRange);
818        }
819        break;
820#endif
821
822    default:
823        BDBG_ERR(("unsupported timebase source type"));
824        return NEXUS_INVALID_PARAMETER;
825    }
826
827#if B_HAS_DSS
828    rc = BXPT_PCR_DirecTv_SetPcrMode(pcr, timebase->isDss?BXPT_PcrMode_eDirecTv:BXPT_PcrMode_eMpeg);
829    if (rc) {return BERR_TRACE(rc);}
830#endif
831
832    BXPT_PCR_FreezeIntegrator(pcr, pSettings->freeze);
833
834    timebase->settings = *pSettings;
835
836    rc = NEXUS_Timebase_P_SetTwoPcrErrorMonitor(timebase, false);
837    if (rc) return BERR_TRACE(rc);
838
839    return 0;
840}
841
842NEXUS_Error NEXUS_Timebase_SetSettings(NEXUS_Timebase timebase, const NEXUS_TimebaseSettings *pSettings)
843{
844    NEXUS_TimebaseHandle handle;
845
846    handle = NEXUS_Timebase_Resolve_priv(timebase);
847
848    if (handle)
849    {
850        return NEXUS_Timebase_P_SetSettings(handle, pSettings);
851    }
852    else
853    {
854        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
855    }
856}
857
858void NEXUS_Timebase_P_GetSettings(NEXUS_TimebaseHandle timebase, NEXUS_TimebaseSettings *pSettings)
859{
860    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
861    *pSettings = timebase->settings;
862}
863
864void NEXUS_Timebase_GetSettings(NEXUS_Timebase timebase, NEXUS_TimebaseSettings *pSettings)
865{
866    NEXUS_TimebaseHandle handle;
867
868    handle = NEXUS_Timebase_Resolve_priv(timebase);
869
870    if (handle)
871    {
872        NEXUS_Timebase_P_GetSettings(handle, pSettings);
873    }
874    else
875    {
876        BERR_TRACE(NEXUS_INVALID_PARAMETER);
877    }
878}
879
880static int NEXUS_Timebase_P_NextAvailable(void)
881{
882    int next = -1;
883    unsigned i = 0;
884   
885    for (i = 0; i < NEXUS_NUM_TIMEBASES; i++) 
886    {
887        if (!pTransport->timebase[i].acquired) 
888        {
889            next = i;
890            break;
891        }
892    }
893
894    return next;
895}
896
897NEXUS_TimebaseHandle NEXUS_Timebase_P_Open(unsigned index)
898{
899    NEXUS_TimebaseHandle handle = NULL;
900
901    if (index == NEXUS_ANY_ID)
902    {
903        int next = NEXUS_Timebase_P_NextAvailable();
904        if (next == -1)
905        {
906            BERR_TRACE(NEXUS_NOT_AVAILABLE);
907            goto end;
908        }
909        else
910        {
911            index = (unsigned)next;
912        }
913    }
914   
915    if (index >= NEXUS_NUM_TIMEBASES) 
916    {
917        BERR_TRACE(NEXUS_INVALID_PARAMETER);
918        goto end;
919    }
920
921    if (!pTransport->timebase[index].acquired) 
922    {
923        pTransport->timebase[index].acquired = true;
924        BDBG_MSG(("Allocating timebase %u to client %p", index, nexus_transport_client()));
925        handle = &pTransport->timebase[index];
926    }
927    else 
928    {
929        BERR_TRACE(NEXUS_NOT_AVAILABLE);
930    }
931
932end:
933    return handle;
934}
935
936NEXUS_Timebase NEXUS_Timebase_Open(unsigned index)
937{
938    NEXUS_TimebaseHandle handle = NULL;
939    handle = NEXUS_Timebase_P_Open(index);
940    /* here we cast to the enum, but it is really a pointer */
941    return handle?(NEXUS_Timebase)handle:NEXUS_Timebase_eInvalid;
942}
943
944void NEXUS_Timebase_P_Close(NEXUS_TimebaseHandle timebase)
945{
946    NEXUS_TimebaseSettings settings;
947   
948    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
949
950    /* revert to default known state */
951    NEXUS_Timebase_GetDefaultSettings_priv(&settings);
952    NEXUS_Timebase_P_SetSettings(timebase, &settings);
953
954    /* this may unregister enum variant usage, if that usage was done
955    in an unprotected client *after* a protected client already acquired
956    the resource */
957    timebase->acquired = false;
958
959    BDBG_MSG(("Client %p releasing timebase %u", nexus_transport_client(), timebase->hwIndex));
960}
961
962void NEXUS_Timebase_Close(NEXUS_Timebase timebase)
963{
964    NEXUS_TimebaseHandle handle = NULL;
965
966    handle = NEXUS_Timebase_Resolve_priv(timebase);
967
968    if (handle)
969    {
970        NEXUS_Timebase_P_Close(handle);
971    }
972    else
973    {
974        BDBG_ERR(("You may be attempting to close the enum variant of this resource.  Please ensure you are passing the resource returned when you called open."));
975        BERR_TRACE(NEXUS_INVALID_PARAMETER);
976    }
977}
978
979static void NEXUS_Timebase_P_Monitor_isr(void *context, int param)
980{
981    NEXUS_TimebaseHandle timebase = context;
982    NEXUS_TimebaseStatus *pStatus = &timebase->status;
983    BSTD_UNUSED(param);
984
985    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
986
987    BDBG_MSG(("Timebase %u: received PCR", timebase->hwIndex));
988    pStatus->pcrValid = true;
989    pStatus->pcrCount++;
990    NEXUS_IsrCallback_Fire_isr(timebase->monitorCallback);
991
992#if NEXUS_HAS_ASTM
993    if (timebase->astm.settings.enabled)
994    {
995        if (timebase->astm.settings.pcrReceived_isr)
996        {
997            timebase->astm.settings.pcrReceived_isr(timebase->astm.settings.callbackContext, timebase->hwIndex);
998        }
999    }
1000#endif
1001}
1002
1003NEXUS_Error NEXUS_Timebase_P_StartMonitor(NEXUS_TimebaseHandle timebase)
1004{
1005    BERR_Code rc;
1006    BINT_Id pcr_int;
1007
1008    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
1009 
1010    BDBG_MSG(("start monitor %d", timebase->hwIndex));
1011
1012    rc = BXPT_PCR_GetIntId( timebase->hwIndex, BXPT_PCR_IntName_ePhaseCompare, &pcr_int );
1013    if (rc) return BERR_TRACE(rc);
1014
1015    rc = BINT_CreateCallback(&timebase->intMonitorCallback, g_pCoreHandles->bint, pcr_int, NEXUS_Timebase_P_Monitor_isr, timebase, 0);
1016    if (rc) return BERR_TRACE(rc);
1017    rc = BINT_EnableCallback(timebase->intMonitorCallback);
1018    if (rc) return BERR_TRACE(rc);
1019    return 0;
1020}
1021
1022void NEXUS_Timebase_P_StopMonitor(NEXUS_TimebaseHandle timebase)
1023{
1024     BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
1025
1026    if (timebase->intMonitorCallback) {
1027        BINT_DisableCallback(timebase->intMonitorCallback);
1028        BINT_DestroyCallback(timebase->intMonitorCallback);
1029        timebase->intMonitorCallback = NULL;
1030    }
1031
1032    /* clean up in case it was left on */
1033    (void)NEXUS_Timebase_P_SetTwoPcrErrorMonitor(timebase, true);
1034}
1035
1036static void NEXUS_Timebase_P_TwoPcrError_isr( void *context, int param )
1037{
1038    NEXUS_TimebaseHandle timebase = context;
1039    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
1040    BSTD_UNUSED(param);
1041    timebase->status.pcrErrors++;
1042    BDBG_WRN(("Timebase %u: pcrError", timebase->hwIndex));
1043    NEXUS_IsrCallback_Fire_isr(timebase->pcrErrorCallback);
1044}
1045
1046static NEXUS_Error NEXUS_Timebase_P_SetTwoPcrErrorMonitor(NEXUS_TimebaseHandle timebase, bool forceOff)
1047{
1048    BINT_Id dpcrErrorIntId;
1049    bool install = false;
1050
1051    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
1052
1053    install = (timebase->settings.sourceType == NEXUS_TimebaseSourceType_ePcr &&
1054               timebase->settings.sourceSettings.pcr.pidChannel &&
1055               timebase->settings.pcrErrorCallback.callback &&
1056               !forceOff);
1057
1058    if ( install ) {
1059        NEXUS_IsrCallback_Set(timebase->pcrErrorCallback, &timebase->settings.pcrErrorCallback);
1060    }
1061    else {
1062        NEXUS_IsrCallback_Set(timebase->pcrErrorCallback, NULL);
1063    }
1064
1065    if (install && !timebase->intPcrErrorCallback) {
1066        BERR_Code rc;
1067        BDBG_MSG(("Installing DPCR%u TWO_PCR_ERROR interrupt handler", timebase->hwIndex));
1068
1069        rc = BXPT_PCR_GetIntId( timebase->hwIndex, BXPT_PCR_IntName_eTwoPcrErrors, &dpcrErrorIntId );
1070        if (rc) return BERR_TRACE(rc);
1071
1072        rc = BINT_CreateCallback(&timebase->intPcrErrorCallback, g_pCoreHandles->bint, dpcrErrorIntId, NEXUS_Timebase_P_TwoPcrError_isr, timebase, 0);
1073        if (rc) return BERR_TRACE(rc);
1074        rc = BINT_EnableCallback(timebase->intPcrErrorCallback);
1075        if (rc) return BERR_TRACE(rc);
1076    }
1077    else if (!install && timebase->intPcrErrorCallback) {
1078        BINT_DisableCallback(timebase->intPcrErrorCallback);
1079        BINT_DestroyCallback(timebase->intPcrErrorCallback);
1080        timebase->intPcrErrorCallback = NULL;
1081    }
1082
1083    return NEXUS_SUCCESS;
1084}
1085
1086NEXUS_Error NEXUS_Timebase_GetStatus_priv_isr(NEXUS_TimebaseHandle timebase, NEXUS_TimebaseStatus *pStatus)
1087{
1088    NEXUS_Error rc = NEXUS_SUCCESS;
1089    uint32_t hi, lo;
1090    int32_t error;
1091
1092    NEXUS_ASSERT_MODULE();
1093
1094    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
1095
1096    *pStatus = timebase->status;
1097
1098    do
1099    {
1100#if B_HAS_DSS
1101        if (timebase->isDss)
1102        {
1103            BXPT_PCR_DirecTv_GetLastPcr(timebase->pcr, &hi);
1104            pStatus->lastValue = hi;
1105            pStatus->lastValueLo = 0;
1106        }
1107        else
1108#endif
1109        {
1110            BXPT_PCR_GetLastPcr_isr(timebase->pcr, &hi, &lo);
1111            pStatus->lastValue = hi;
1112            pStatus->lastValueLo = lo;
1113        }
1114        BXPT_PCR_GetPhaseError_isr(timebase->pcr, &error);
1115        /* read again to make sure that the phase goes with the correct PCR */
1116#if B_HAS_DSS
1117        if (timebase->isDss)
1118        {
1119            BXPT_PCR_DirecTv_GetLastPcr(timebase->pcr, &hi);
1120        }
1121        else
1122#endif
1123        {
1124            BXPT_PCR_GetLastPcr_isr(timebase->pcr, &hi, &lo);
1125        }
1126    } while (pStatus->lastValue != hi);
1127
1128    pStatus->lastError = error;
1129
1130    return rc;
1131}
1132
1133NEXUS_Error NEXUS_Timebase_GetStatus(NEXUS_Timebase timebase, NEXUS_TimebaseStatus *pStatus)
1134{
1135    NEXUS_Error rc = NEXUS_SUCCESS;
1136    NEXUS_TimebaseHandle handle;
1137
1138    handle = NEXUS_Timebase_Resolve_priv(timebase);
1139
1140    if (handle)
1141    {
1142        BKNI_EnterCriticalSection();
1143        rc = NEXUS_Timebase_GetStatus_priv_isr(handle, pStatus);
1144        BKNI_LeaveCriticalSection();
1145    }
1146    else
1147    {
1148        rc = BERR_TRACE(NEXUS_INVALID_PARAMETER);
1149    }
1150
1151    return rc;
1152}
1153
1154NEXUS_Error NEXUS_Timebase_ResetStatus(NEXUS_Timebase timebase)
1155{
1156    NEXUS_Error rc = NEXUS_SUCCESS;
1157    NEXUS_TimebaseHandle handle;
1158
1159    handle = NEXUS_Timebase_Resolve_priv(timebase);
1160
1161    if (handle)
1162    {
1163        BKNI_Memset(&handle->status, 0, sizeof(handle->status));
1164        /* this sets count to 0 and valid to false. */
1165        handle->status.sourceType = handle->settings.sourceType;
1166
1167#if NEXUS_HAS_ASTM
1168        if (handle->astm.settings.enabled)
1169        {
1170            if (handle->astm.settings.clockCoupling == NEXUS_TimebaseClockCoupling_eInternalClock)
1171            {
1172                handle->status.sourceType = NEXUS_TimebaseSourceType_eFreeRun;
1173            }
1174        }
1175#endif
1176    }
1177    else
1178    {
1179        rc = BERR_TRACE(NEXUS_INVALID_PARAMETER);
1180    }
1181
1182    return rc;
1183}
1184
1185#if NEXUS_HAS_ASTM
1186void NEXUS_Timebase_GetAstmSettings_priv(
1187    NEXUS_TimebaseHandle timebase,
1188    NEXUS_TimebaseAstmSettings * pAstmSettings  /* [out] */
1189)
1190{
1191    NEXUS_ASSERT_MODULE();
1192    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl); 
1193
1194    *pAstmSettings = timebase->astm.settings;
1195}
1196
1197NEXUS_Error NEXUS_Timebase_SetAstmSettings_priv(
1198    NEXUS_TimebaseHandle timebase,
1199    const NEXUS_TimebaseAstmSettings * pAstmSettings
1200)
1201{
1202    NEXUS_Error rc = NEXUS_SUCCESS;
1203
1204    NEXUS_ASSERT_MODULE();
1205    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
1206
1207    /* copy settings as-is, this way ASTM will always get what it set */
1208    timebase->astm.settings = *pAstmSettings;
1209
1210    /* if ASTM is internally permitted, reapply settings */
1211    rc = NEXUS_Timebase_P_SetSettings(timebase, &timebase->settings);
1212
1213    return rc;
1214}
1215#endif /* NEXUS_HAS_ASTM */
1216
1217NEXUS_Error NEXUS_Timebase_GetIndex_priv(
1218    NEXUS_TimebaseHandle timebase,
1219    unsigned * pIndex
1220    )
1221{
1222    NEXUS_ASSERT_MODULE();
1223    BDBG_ASSERT(pIndex);
1224    BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl);
1225    *pIndex = timebase->hwIndex;
1226    return 0;
1227}
1228
1229NEXUS_Error NEXUS_Timebase_SetHdDviFrameRate( NEXUS_Timebase timebase, NEXUS_VideoFrameRate frameRate )
1230{
1231    NEXUS_TimebaseHandle handle;
1232    handle = NEXUS_Timebase_Resolve_priv(timebase);
1233    if (!handle) {
1234        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1235    }
1236   
1237    handle->hdDviFrameRate = frameRate;
1238    return NEXUS_Timebase_P_SetSettings(handle, &handle->settings);
1239}
1240
1241NEXUS_Error NEXUS_Timebase_SetVdecFrameRate( NEXUS_Timebase timebase, NEXUS_VideoFrameRate frameRate )
1242{
1243    NEXUS_TimebaseHandle handle;
1244    handle = NEXUS_Timebase_Resolve_priv(timebase);
1245    if (!handle) {
1246        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1247    }
1248   
1249    handle->vdecFrameRate = frameRate;
1250    return NEXUS_Timebase_P_SetSettings(handle, &handle->settings);
1251}
Note: See TracBrowser for help on using the repository browser.