📄 cquad.c
字号:
/******************************************************************************//* cquad.c : specific code for (QUAD + EM840X) board* REALmagic Quasar Hardware Library* Created by Aurelia Popa-Radu* Copyright Sigma Designs Inc* Sigma Designs Proprietary and confidential* Created on 8/7/01* Description:/******************************************************************************//****h* HwLib/CQuad_Implementation * DESCRIPTION * CQuad implementation of the IDecoderBoard interface. * QUAD uses four EM840X, EM9038 components to implement 4 digital overlay output, * 4 independent TV output, 4 video multiplexed in one 480P output. * QUAD hardware board should be treated by the HwLib's user like 4 independent boards: * - one QUADMASTER - this EM840X owns and controls EM9038 and switches the * necessary hardware signals for the other three EM840X. * - three QUADSLAVEs - switching modes should be in sync for all 4 EM840X. * Identified by HwLib reading MD5,MD4,MD3,MD2 pins = 0000 (MDCFG_REFERENCE), * version of the EM84 and by the PCI cofiguration SubsystemID = 0xF0 for * QUADMASTER and 0xF1, 0xF2,0xF3 for QUADSLAVEs. * PIO0 - IIC Clock for EM9038, Eeprom * PIO1 - IIC Data for EM9038, Eeprom * PIO2 - * PIO3 - * PIO4 - nDIGENABLE_PIO = 1/0 disable/enable digital Vga header * PIO5 - * PIO6 - ENABLE_VRDY_PIO = = 1/0 enable/disable VRDY * PIO7 - DVCLKSEL_27MHz_PCLK_PIO = 1/0 selects 27 MHz / PCLK0 for VClk for the 3 slaves * Implementation is based on CVE2000. * Specific implementation: * QRESULT CQuad__UpdateOverlay(IDecoderBoard* pIDecoderBoard) * QRESULT CQuad__VidSetVGATV(IDecoderBoard* pIDecoderBoard, DWORD VideoRunning, DWORD TvOut ) * QRESULT CQuad__AudioSetSampleRate(IDecoderBoard* pIDecoderBoard, DWORD Rate)/******************************************************************************/#include "pch.h"#if defined QUAD_BRD || defined QUAD7X_BRD#include "cqsrbrd.h"#undef NEW_4TVvoid CQuad__InitMasterParams480P(IDecoderBoard* pIDecoderBoard){ CQuasarBoard *this = (CQuasarBoard*) pIDecoderBoard; DWORD PixelFreq = 66667000; // Hz DWORD VideoPixelsPerLine = 1440; // full screen: 1440x480 DWORD VideoLinesPerFrame = 480; this->MasterParams.VSyncTotal = 525;// lines this->MasterParams.VSyncActive = 3; // lines this->MasterParams.HSyncTotal = VideoPixelsPerLine + 324;// 1764 pixels this->MasterParams.HSyncActive = 225; // pixels this->MasterParams.HFrequency = PixelFreq / this->MasterParams.HSyncTotal;// 37.793 kHz, 71.9868Hz QDbgLog((QLOG_TRACE, QDebugLevelWarning, TEXT(" MasterParams for QUAD %dx%d %dHz %dHz %dKHz"), VideoPixelsPerLine, VideoLinesPerFrame, this->MasterParams.HFrequency, this->MasterParams.HFrequency/this->MasterParams.VSyncTotal, PixelFreq/1000)); this->MasterParams.x = this->MasterParams.HSyncActive + 33; // pixels this->MasterParams.y = 24; // lines this->MasterParams.w = VideoPixelsPerLine; // pixels this->MasterParams.h = VideoLinesPerFrame; // lines this->MasterParams.HFrequency /= 100;}void CQuad__HdtvUpdateVideoWindow(IDecoderBoard* pIDecoderBoard){ CQuasarBoard *this = (CQuasarBoard*) pIDecoderBoard; WND VisWnd, FrameWnd, HdtvWnd, OsdWnd; OsdWnd = this->OsdWnd; HdtvWnd = *(WND*)&this->MasterParams; this->RealDestWnd.x = 0; this->RealDestWnd.y = 0; this->RealDestWnd.w = HdtvWnd.w; this->RealDestWnd.h = HdtvWnd.h; if ( (this->OverlayFlags & VIDEO_HDTV_DEST_ENABLE) || (this->NewOverlayFlags & VIDEO_HDTV_DEST_ENABLE) ) { // use destination window FrameWnd = VisWnd = this->DstWnd; this->RealDestWnd.w = this->DstWnd.w; this->RealDestWnd.h = this->DstWnd.h; CQuasarBoard__LimitDestByScreen(&VisWnd, &OsdWnd, HdtvWnd.w, HdtvWnd.h); if(this->OverlayFlags & VIDEO_ZOOM_ENABLE) CQuasarBoard__ZoomCalc(pIDecoderBoard, &FrameWnd); VisWnd.x = (VisWnd.x + HdtvWnd.x) & ~1; VisWnd.y += HdtvWnd.y; FrameWnd.x = (FrameWnd.x + HdtvWnd.x) & ~1; FrameWnd.y += HdtvWnd.y; OsdWnd.x = (OsdWnd.x + HdtvWnd.x) & ~1; OsdWnd.y = (OsdWnd.y + HdtvWnd.y) & ~1; } else { // divide the screen in 4 equal area HdtvWnd.w = HdtvWnd.w / 2; HdtvWnd.h = HdtvWnd.h / 2; switch( this->PciSubsystemID ) { case 0xF1: HdtvWnd.x += HdtvWnd.w; break; case 0xF2: HdtvWnd.y += HdtvWnd.h; break; case 0xF3: HdtvWnd.x += HdtvWnd.w; HdtvWnd.y += HdtvWnd.h; break; } FrameWnd = VisWnd = HdtvWnd; CQuasarBoard__LimitDestByScreen(NULL, &OsdWnd, HdtvWnd.w, HdtvWnd.h); if(this->OverlayFlags & VIDEO_ZOOM_ENABLE) CQuasarBoard__ZoomCalc(pIDecoderBoard, &FrameWnd); OsdWnd.x += HdtvWnd.x; OsdWnd.y += HdtvWnd.y; } IDecoder_SetKmin(this->m_pIDecoder, this->SrcWnd.w + 6, this->HFrequency * 100); IDecoder_UpdateVideoWindow(this->m_pIDecoder, &VisWnd, &FrameWnd, NULL, &OsdWnd, &this->OsdHiLiWnd, this->LetterBox | ((this->OverlayFlags & OSD_VIDEO_INDEPENDENT_DEST)? OSD_VIDEO_INDEPENDENT:0) );}QRESULT CQuad__UpdateOverlay(IDecoderBoard* pIDecoderBoard){ CQuasarBoard *this = (CQuasarBoard*) pIDecoderBoard; if(this->TvOut == SET_HDTV) CQuad__HdtvUpdateVideoWindow(pIDecoderBoard); else // SET_TV, SET_VGA CQuasarBoard__TVVMIUpdateVideoWindow(pIDecoderBoard); return Q_OK;}#endif // QUAD_BRD | QUAD7X_BRD#if defined QUAD_BRD#include "cqsrbrd.h"#define ENABLE_VRDY_PIO PIO6#define DVCLKSEL_27MHz_PCLK_PIO PIO7QRESULT CQuad__VidSetVGATV(IDecoderBoard* pIDecoderBoard, DWORD VideoRunning, DWORD TvOut ){ CQuasarBoard *this = (CQuasarBoard*) pIDecoderBoard; DWORD ccir; if(TvOut == SET_VGA) return E_NOT_SUPPORTED; this->TvOut = TvOut; if(VideoRunning & RST_DC) IDecoder_StopDisplayController(this->m_pIDecoder); switch(this->TvOut) {#ifdef NEW_4TV case SET_TV: ccir = CCIR_601 | NO_INVERT_FIELD | SYNC_ENABLE_1; ITvEncoder_SetCurrentYcYuvRgb(this->m_pITvEncoder, this->ReqYcYuvRgb); ITvEncoder_ProgramTV(this->m_pISigmaTv, TVSLAVE, 16, ccir, this->Standard_TvOut, 0); IDecoder_QuasarSlave( this->m_pIDecoder, 16, ccir, (this->Standard_TvOut == SET_PAL) ? &this->MasterParamsPal:&this->MasterParamsNtsc, VSHS_ACTIVE_LOW, Q3CTRL2_NOINTERLACED | DIGITAL_DATA_ENABLE); if( this->m_pIExtTv ) { ITvEncoder_ProgramTV(this->m_pIExtTv, TVMASTER, 16, ccir, this->Standard_TvOut, VideoRunning & ~RST_DC); } CQuasarBoard__TVVMIUpdateVideoWindow(pIDecoderBoard); if( this->m_pIExtTv ) { OSTimeDelay(100000); // wait 100 ms to not see garbage on TV when the switch occur ITvEncoder_DisableTVBlackout(this->m_pIExtTv); } break;#else // NEW_4TV case SET_TV: ccir = this->pRegistry->Ccir_656 | (this->pRegistry->InvertField << 12) | (this->pRegistry->SyncEnable << 4); IDecoderBoard_SelectVClk(pIDecoderBoard, TvVClk, NULL, 0); // SigmaTv master, Quasar slave ITvEncoder_SetCurrentYcYuvRgb(this->m_pITvEncoder, this->ReqYcYuvRgb); ITvEncoder_ProgramTV(this->m_pISigmaTv, TVMASTER, 8, ccir, this->Standard_TvOut, VideoRunning & ~RST_DC); IDecoder_QuasarSlave( this->m_pIDecoder, 8, ccir, (this->Standard_TvOut == SET_PAL) ? &this->MasterParamsPal:&this->MasterParamsNtsc, VSHS_ACTIVE_LOW, Q3CTRL2_NOINTERLACED | DIGITAL_DATA_ENABLE); if( this->BoardVersion == QUADMASTER ) { // Hyde Mpeg FullScreen on VGA monitor and power down the Dacs for NovaLite IAnalogOverlay_SetTv(this->m_pINovaLite); IDecoder_WritePIO(this->m_pIDecoder, ENABLE_VRDY_PIO, 0); IDecoder_WritePIO(this->m_pIDecoder, DVCLKSEL_27MHz_PCLK_PIO, 1); // 27 MHz for slaves } CQuasarBoard__TVVMIUpdateVideoWindow(pIDecoderBoard); break;#endif // NEW_4TV case SET_HDTV_SUBD: case SET_HDTV: ccir = CCIR_601 | NO_INVERT_FIELD | SYNC_ENABLE_1; // QUADMASTER master, QUADSLAVE slaves, SigmaTv slave CQuad__InitMasterParams480P(pIDecoderBoard); ITvEncoder_ProgramTV(this->m_pISigmaTv, TVSLAVE, 8, ccir, this->Standard_TvOut, 0); if( this->BoardVersion == QUADMASTER ) { IDecoder_WritePIO(this->m_pIDecoder, ENABLE_VRDY_PIO, 1); IDecoder_WritePIO(this->m_pIDecoder, DVCLKSEL_27MHz_PCLK_PIO, 0); // PCLK0 for slaves // Mpeg FullScreen on VGA monitor for NovaLite IAnalogOverlay_SetVGA(this->m_pINovaLite); // Quasar master progressive VSync=60Hz, HSync=32KHz, PixelFreq=27MHz IDecoder_QuasarMaster( this->m_pIDecoder, 16, ccir, &this->MasterParams, DISPLAY_NONINTERLACED, VSHS_ACTIVE_LOW, Q3CTRL2_NOINTERLACED | DIGITAL_DATA_ENABLE); } else // QUADSLAVE { // Quasar slave progressive VSync=60Hz, HSync=32KHz, PixelFreq=27MHz IDecoder_QuasarSlave( this->m_pIDecoder, 16, ccir, &this->MasterParams, VSHS_ACTIVE_LOW, Q3CTRL2_NOINTERLACED | DIGITAL_DATA_ENABLE); } this->HFrequency = this->MasterParams.HFrequency; CQuad__HdtvUpdateVideoWindow(pIDecoderBoard); break; } return Q_OK;}QRESULT CQuad__AudioSetSampleRate(IDecoderBoard* pIDecoderBoard, DWORD Rate){ CQuasarBoard *this = (CQuasarBoard*) pIDecoderBoard; BYTE K, N, M; // NovaLite PLL (N+2)/( (N+2)*2^k ) = divider for 27 MHz if( (!(this->BoardAudioRate & FORCED_HW_UPDATE)) && (this->BoardAudioRate == Rate) ) return Q_OK; this->BoardAudioRate = Rate & ~FORCED_HW_UPDATE; // use most significant bit to force programming QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" CQuad__AudioSetSampleRate= %lu"), this->BoardAudioRate)); IDecoder_SetAudioSampleRate(this->m_pIDecoder, this->BoardAudioRate); switch(this->BoardVersion) { case QUADMASTER: switch(this->BoardAudioRate) { case 32000: // 8,191,747.57Hz instead of 8,192,000Hz, ppm=-30.81 K = 3; N = 123; M = 101; break; case 44100: // 11,289,823.01Hz instead of 11.289,600Hz, ppm=19.75 K = 2; N = 187; M = 111; break; default: case 48000: // 12,288,461.54Hz instead of 12,288,000Hz, ppm=37.56 K = 2; N = 69; M = 37; break; } // program audio clock through NovaLite IAnalogOverlay_ProgramPLL(this->m_pINovaLite, PLL3, N, M, K); // enable spdif through NovaLite IAnalogOverlay_Write(this->m_pINovaLite, 0xa, 0x08); break; } return Q_OK;}void CQuad__InitVtable(IDecoderBoard* pIDecoderBoard){ CQuasarBoard* this = (CQuasarBoard*) pIDecoderBoard; this->lpVtbl->HwReset = CVE2000__HwReset; this->lpVtbl->SetCustomTvHdtv = CVE2000__SetCustomTvHdtv; this->lpVtbl->UpdateOverlay = CQuad__UpdateOverlay; this->lpVtbl->VidSetVGATV = CQuad__VidSetVGATV; this->lpVtbl->AudioSetSampleRate = CQuad__AudioSetSampleRate;}QRESULT CQuad__SpecificCreateInstance(IDecoderBoard* pIDecoderBoard, DWORD dwInstance){ CQuasarBoard* this = (CQuasarBoard*) pIDecoderBoard;#ifdef NEW_4TV DWORD TvEncoderId = 1;#endif // NEW_4TV this->BoardCapabilities |= MPEG_CAPABILITY_480P; this->pRegistry->Ccir_656 = CCIR_656; this->pRegistry->SyncEnable = 0; // by default disable VS,HS,VVLD for 656 this->pRegistry->TvOut = SET_TV | SET_NTSC | SET_ONETOONE; this->TvOut = SET_TV; // overwrite necessary values CQuad__InitVtable(pIDecoderBoard); this->DeviceId = VENTURA2000_DEVICEID; if( this->PciSubsystemID == 0xF0 ) // QUAD master { this->BoardVersion = QUADMASTER;#ifdef NEW_4TV // Create CTvEncoder instance if( ModCreateInstance (dwInstance, &CLSID_CTVENCODER, &IID_ITVENCODER, (void**)&this->m_pIExtTv) != NOERROR) { return Q_FAIL; } ISetI2CpIO_SetI2C_params( this->m_pISetI2CpIO, I2C_PIO_DATA, I2C_PIO_CLOCK); ITvEncoder_Init(this->m_pIExtTv, &TvEncoderId); ITvEncoder_SetRegistry(this->m_pIExtTv, this->pRegistry); this->m_pITvEncoder = this->m_pIExtTv; // used for 4 mixed TvOut#endif // NEW_4TV // Create CNovaLite instance if( ModCreateInstance (dwInstance, &CLSID_CNOVALITE, &IID_IANALOGOVERLAY, (void**)&this->m_pINovaLite) != NOERROR ) { return Q_FAIL; } ISetI2CpIO_SetI2C_params( this->m_pISetI2CpIO, SECOND_I2C_DATA_PIO, SECOND_I2C_PIO_CLOCK); IAnalogOverlay_Init(this->m_pINovaLite, NULL); IAnalogOverlay_SetRegistry(this->m_pINovaLite, this->pRegistry); } else if( (this->PciSubsystemID & 0xFC) == 0xF0 ) // QUAD slaves this->BoardVersion = QUADSLAVE; else return Q_FAIL; this->SubId = (this->BoardVersion>>8); if( ((IDecoder_ReadReg(this->m_pIDecoder, DRAM_startup) & 0x3C) != MDCFG_REFERENCE) || ((this->PciSubsystemID & 0xFC) != 0xF0) ) QDbgLog((QLOG_TRACE, QDebugLevelWarning, TEXT("\n\nERROR: Create QUAD is FORCED !") )); { DWORD Value = I2SInv_SCkinSCIN_Jda1CkinGCK_ScinIN_DamckIN; IDecoder_SetProperty(this->m_pIDecoder, DECODER_SET, edecAudioInOutConfig, 0, &Value, sizeof(DWORD), NULL); Value = 16; IDecoder_SetProperty(this->m_pIDecoder, DECODER_SET, edecAudioDacBitsPerSample, 0, &Value, sizeof(DWORD), NULL); } return Q_OK;}#endif // QUAD_BRD#if defined QUAD_BRD && !defined ANY_BRDQRESULT CreateInstance(DWORD* pInstance, void* pHwLibConf){ QRESULT qr = CommonCreateInstance(pInstance, pHwLibConf); if( QSUCCEEDED(qr) ) qr = CQuad__SpecificCreateInstance(g_pIDecoderBoard[*pInstance], *pInstance); if( QFAILED(qr) ) { CQuasarBoard__DeleteObjects(g_pIDecoderBoard[*pInstance]); g_pIDecoderBoard[*pInstance] = 0; return E_CREATE_INSTANCE_FAILED; } return Q_OK;}#endif // QUAD_BRD && !ANY_BRD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -