| 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 | |
|---|
| 279 | BDBG_MODULE(nexus_timebase); |
|---|
| 280 | |
|---|
| 281 | static NEXUS_Error NEXUS_Timebase_P_SetTwoPcrErrorMonitor(NEXUS_TimebaseHandle timebase, bool forceOff); |
|---|
| 282 | |
|---|
| 283 | NEXUS_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 | |
|---|
| 332 | void 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. */ |
|---|
| 367 | NEXUS_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 | |
|---|
| 399 | NEXUS_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 | |
|---|
| 418 | NEXUS_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 | |
|---|
| 460 | NEXUS_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 | ¢erFreq); |
|---|
| 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 | ¢erFreq); |
|---|
| 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 | |
|---|
| 842 | NEXUS_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 | |
|---|
| 858 | void NEXUS_Timebase_P_GetSettings(NEXUS_TimebaseHandle timebase, NEXUS_TimebaseSettings *pSettings) |
|---|
| 859 | { |
|---|
| 860 | BDBG_OBJECT_ASSERT(timebase, NEXUS_TimebaseImpl); |
|---|
| 861 | *pSettings = timebase->settings; |
|---|
| 862 | } |
|---|
| 863 | |
|---|
| 864 | void 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 | |
|---|
| 880 | static 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 | |
|---|
| 897 | NEXUS_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 | |
|---|
| 932 | end: |
|---|
| 933 | return handle; |
|---|
| 934 | } |
|---|
| 935 | |
|---|
| 936 | NEXUS_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 | |
|---|
| 944 | void 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 | |
|---|
| 962 | void 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 | |
|---|
| 979 | static 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 | |
|---|
| 1003 | NEXUS_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 | |
|---|
| 1022 | void 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 | |
|---|
| 1036 | static 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 | |
|---|
| 1046 | static 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 | |
|---|
| 1086 | NEXUS_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 | |
|---|
| 1133 | NEXUS_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 | |
|---|
| 1154 | NEXUS_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 |
|---|
| 1186 | void 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 | |
|---|
| 1197 | NEXUS_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 | |
|---|
| 1217 | NEXUS_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 | |
|---|
| 1229 | NEXUS_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 | |
|---|
| 1241 | NEXUS_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 | } |
|---|