📄 csm2288.c
字号:
OSmemcpy((void*)this->XferUcodeParameters.SysLinAddr, (BYTE*)pUCode+offset, maxxfer); t0 = OSTimeGetTime(); IDecoder_WriteDataToLBC(this->m_pIDecoder, HostMaster_W4_LWCH0_Ucode | Sm2288_Interface | LBC_Swap_Bytes, this->XferUcodeParameters.SysPhysAddr, maxxfer); while( IDecoder_ReadReg(this->m_pIDecoder, QPM_from_host_xfer_cnt) ) { OSTimeDelay(1000); if ( (OSTimeGetTime()-t0) > 10 ) { QDbgLog((QLOG_TRACE, QDebugLevelWarning, TEXT(" Csm2288__HwReset XFER_UCODE_BURST_SYS FAILED %d ms"), OSTimeGetTime()-t0)); return Q_FAIL; } } offset+=maxxfer; if (offset==totalsize) break; } IDecoder_WriteReg(this->m_pIDecoder, 0x1fe5, Mux1); IDecoder_WriteReg(this->m_pIDecoder, 0x1fe6, Mux2); } else // INFO_SM_XFER_UCODE_BURST_DRAM { // intel burst lasts about 90000 microseconds. DWORD maxxfer,offset=0; if (this->XferUcodeParameters.DramSizeInBytes == 0) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" Csm2288__HwReset XFER_UCODE_BURST_DRAM FAILED"))); return Q_FAIL; } QDbgLog((QLOG_TRACE, QDebugLevelWarning, TEXT(" Csm2288__HwReset XFER_UCODE_BURST_DRAM"))); while(1) { // use 32k of Dram (0x8000 bytes) at a harcoded address to // load the StreamMachine microcode first in Dram (slave), maxxfer = min(totalsize-offset, this->XferUcodeParameters.DramSizeInBytes); #if 1 IDecoder_WriteDramSlave(this->m_pIDecoder, this->XferUcodeParameters.DramAddr, (DWORD *)((BYTE*)pUCode+offset), maxxfer);#else //test W4 transfer when VideoIn is already started #define W0 0x1C10 #define W4 0x1CF0 temp = IDecoder_ReadReg(this->m_pIDecoder, DRAM_portmux); QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" temp= %x"),temp)); if((temp & DRAM_portmux_CHW0_Mask) == DRAM_portmux_W0_to_CHW0) { CQuasar__ChannelWriteDramSlave(this->m_pIDecoder, W0, this->XferUcodeParameters.DramAddr, (DWORD *)((BYTE*)pUCode+offset), maxxfer); } else { IDecoder_WriteReg(this->m_pIDecoder, 0x1fe5, 1); IDecoder_WriteReg(this->m_pIDecoder, 0x1fe6, 5); CQuasar__ChannelWriteDramSlave(this->m_pIDecoder, W4, this->XferUcodeParameters.DramAddr, (DWORD *)((BYTE*)pUCode+offset), maxxfer); IDecoder_WriteReg(this->m_pIDecoder, 0x1fe5, 4); IDecoder_WriteReg(this->m_pIDecoder, 0x1fe6, 5); }#endif IDecoder_WriteDataToLBC(this->m_pIDecoder, Dram_CHR0_LWCH0_Ucode | Sm2288_Interface | LBC_Swap_Bytes, this->XferUcodeParameters.DramAddr, maxxfer); OSTimeDelay(2000);// 1500 microseconds has proved to be not enough. offset+=maxxfer; if (offset==totalsize) break; } } if(Info & INFO_SM_WAIT_TXFIFO) { DWORD timeleft=SM2288_RC_TO_TX_DELAY_MS; int i=0; // read four answers within timeout // according to Scott Henry dec 18th 2002 while (1) { DWORD temp=IMpegEncoder_ReadTXFifo(pIMpegEncoder,&timeleft); if (timeleft==0) break; else { // sm2288 firmware version is the second message (Emmanuel) if (i==1) this->CurrentMicrocodeVersion=temp; QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" Csm2288__HwReset TX_FIFO after download ucode= 0x%04x"),temp)); i++; } if (i==4) break; } } if(Info & INFO_SM_PARAMS) { if( pParams == NULL ) { // hardware library params.h table does not exist. QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" Csm2288__HwReset caller did not supply params table"))); // This should be fatal! } else Csm2288__WriteEncodingParams(pIMpegEncoder, pParams, nBytesParams, Info); } if(Info & INFO_SM_START) Csm2288__WriteCommand(pIMpegEncoder, SM2288_START, Info); return Q_OK;}/****f* HwLib/IMpegEncoder_WriteCommand * USAGE * BOOL IMpegEncoder_WriteCommand(IMpegEncoder* pIMpegEncoder, DWORD Command, DWORD Info) * BOOL Csm2288__WriteCommand(IMpegEncoder* pIMpegEncoder, DWORD Command, DWORD Info) * DESCRIPTION * IMpegEncoder_WriteCommand - send encoding parameters to Mpeg encoder hardware * PARAMETERS * IN IMpegEncoder* pIMpegEncoder - pointer to the MpegEncoder object * IN DWORD Command - one of specific MpegEncoder commands. * For SM2288 one of SM2288_STOP, SM2288_START, SM2288_PAUSE, SM2288_RESUME. * IN DWORD Info - use INFO_SM_WAIT_TXFIFO_CMD to wait for acknowledges after writing the parameters./********************************************************************************************/BOOL Csm2288__WriteCommand(IMpegEncoder* pIMpegEncoder, DWORD Command, DWORD Info){ QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" Csm2288__WriteCommand queueing 0x%04x in RC_FIFO"), Command)); Csm2288__Write(pIMpegEncoder, SM2288_RC_FIFO, Command); if(Info & INFO_SM_WAIT_TXFIFO_CMD) { DWORD timeleft=SM2288_RC_TO_TX_DELAY_MS; DWORD temp=IMpegEncoder_ReadTXFifo(pIMpegEncoder,&timeleft); if (timeleft>0) QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" Csm2288__WriteCommand TX_FIFO 0x%04x"), temp)); } return TRUE;}/****f* HwLib/IMpegEncoder_WriteEncodingParams * USAGE * BOOL IMpegEncoder_WriteEncodingParams(IMpegEncoder* pIMpegEncoder, void* pData, DWORD nBytes, DWORD Info) * BOOL Csm2288__WriteEncodingParams(IMpegEncoder* pIMpegEncoder, void* pData, DWORD nBytes, DWORD Info) * DESCRIPTION * IMpegEncoder_WriteEncodingParams - send encoding parameters to Mpeg encoder hardware * PARAMETERS * IN IMpegEncoder* pIMpegEncoder - pointer to the MpegEncoder object * IN void* pData - pointer to the table containing the encoding parameters. The format of data is * specific to the Mpeg encoder hardware. * For SM2288 every parameter is described in a WORD, the HIBYTE is the index and LOBYTE is * the corresponding data. In order to update the parameters written the list should finish with 0xb801. * IN DWORD nBytes - size of the data in bytes * IN DWORD Info - use INFO_SM_WAIT_TXFIFO_PARAMS to wait for acknowledges after writting the parameters./********************************************************************************************/BOOL Csm2288__WriteEncodingParams(IMpegEncoder* pIMpegEncoder, void* pData, DWORD nBytes, DWORD Info){ DWORD i; WORD* pWordParams = (WORD*)pData; // download default parameters for(i=0;i<(nBytes/sizeof(WORD));i++) Csm2288__Write(pIMpegEncoder, SM2288_PARAM_DOWNLOAD, pWordParams[i] ); if(Info & INFO_SM_WAIT_TXFIFO_PARAMS) { DWORD timeleft=SM2288_RC_TO_TX_DELAY_MS; DWORD temp=IMpegEncoder_ReadTXFifo(pIMpegEncoder,&timeleft); if (timeleft>0) QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" Csm2288__WriteEncodingParams TX_FIFO after download params= 0x%04x"), temp )); } return TRUE;}/****f* HwLib/IMpegEncoder_ReadData * USAGE * BOOL IMpegEncoder_ReadData(IMpegEncoder* pIMpegEncoder, DWORD Type, DWORD nBytes) * BOOL Csm2288__ReadData(IMpegEncoder* pIMpegEncoder, DWORD Type, DWORD nBytes) * DESCRIPTION * IMpegEncoder_ReadData - program the encoder to send data through DMA * PARAMETERS * IN IMpegEncoder* pIMpegEncoder - pointer to the MpegEncoder object * IN DWORD Type - audio, video, A/V multiplexed * IN DWORD nBytes - number of bytes to send - multiple of 8/********************************************************************************************/BOOL Csm2288__ReadData(IMpegEncoder* pIMpegEncoder, DWORD Type, DWORD nBytes){ QDbgLog((QLOG_TRACE,QDebugLevelError,TEXT("Csm2288__ReadData: untested code?"))); return FALSE; if(nBytes%8) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" Csm2288__ReadData nBytes=%x NOT MULTIPLE of 8 ???"), nBytes)); return FALSE; } Csm2288__Write(pIMpegEncoder, SM2288_DMA_INFO1, (Type & ~SM2288_INTEL_BURST) | DMA_REQ_POL_HIGH | DMA_READ); Csm2288__Write(pIMpegEncoder, SM2288_DMA_INFO2, 0); // Intel burst mode or Intel single access mode - EM847x doesn't output a DMA_ACK Csm2288__Write(pIMpegEncoder, SM2288_DMA_COUNT, (Type & SM2288_INTEL_BURST) | (nBytes/8)); Csm2288__SetCurrentIrqMask(pIMpegEncoder, DMA_DONE | DMAENABLE); return TRUE;/* ____Next waveforms describes the DMAREQ (active high) and INTR (active low) when executing:IMpegEncoder_HwReset, IDecoderBoard_WriteDataToLBC and IDecoderBoard_ReadDataFromLBC. <HwReset>< WriteDataToLBC >< ReadDataFromLBC > ____ ________________ ________________DMAREQ XXXX |________| |__________________| |__________ ______________________________ _____________________________INTR XXXX |_____| |______ + + + + + + + | | | | | | | | | | | | | Finish the DMA transfer | | | | | program DMA_START in SM2288_DMA_COUNT register | | | | clear SM2288_INT_EN_CTRL register | | | Finish the DMA transfer | | program DMA_START in SM2288_DMA_COUNT register | Program DMA_REQ polarity high Unreset LBC channel = SM reset */}/****f* HwLib/IMpegEncoder_WriteData * USAGE * BOOL IMpegEncoder_WriteData(IMpegEncoder* pIMpegEncoder, DWORD Type, DWORD nBytes) * BOOL Csm2288__WriteData(IMpegEncoder* pIMpegEncoder, DWORD Type, DWORD nBytes) * DESCRIPTION * IMpegEncoder_WriteData - program the encoder to send data through DMA * PARAMETERS * IN IMpegEncoder* pIMpegEncoder - pointer to the MpegEncoder object * IN DWORD Type - audio, video, A/V multiplexed * IN DWORD nBytes - number of bytes to send - multiple of 8/********************************************************************************************/BOOL Csm2288__WriteData(IMpegEncoder* pIMpegEncoder, DWORD Type, DWORD nBytes){ QDbgLog((QLOG_TRACE,QDebugLevelError,TEXT("Csm2288__WriteData: untested code?"))); return FALSE; if(nBytes%8) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" Csm2288__WriteData nBytes=%x NOT MULTIPLE of 8 ???"), nBytes)); return FALSE; } Csm2288__Write(pIMpegEncoder, SM2288_DMA_INFO1, (Type & ~SM2288_INTEL_BURST) | DMA_REQ_POL_HIGH | DMA_WRITE); Csm2288__Write(pIMpegEncoder, SM2288_DMA_INFO2, 0); // Intel burst mode or Intel single access mode - EM847x doesn't output a DMA_ACK Csm2288__Write(pIMpegEncoder, SM2288_DMA_COUNT, (Type & SM2288_INTEL_BURST) ? (DMA_START | (nBytes/8)) : (nBytes/8)); Csm2288__SetCurrentIrqMask(pIMpegEncoder, DMA_DONE); return TRUE;}/****f* HwLib/IMpegEncoder_SetCurrentIrqMask * USAGE * void IMpegEncoder_SetCurrentIrqMask(IMpegEncoder* pIMpegEncoder, DWORD IrqMask) * void Csm2288__SetCurrentIrqMask(IMpegEncoder* pIMpegEncoder, DWORD IrqMask) * DESCRIPTION * IMpegEncoder_SetCurrentIrqMask - sets "CurrentIrqMask" variable and updates the * interrupt mask in firmware/hardware of SM2288. * The possible sources of interrupt from SM2288 are: * I2C_IDLE 0x2000 * DMAENABLE 0x1000 * AS_ALE_PROTECT 0x0800 * DMA_REQ_ACK 0x0200 * DRAM_FIFO_FULL 0x0080 * DRAM_FIFO_EMPTY 0x0040 * RC_FIFO_EMPTY 0x0008 * TX_FIFO_FULL 0x0004 * TX_FIFO_NOT_EMPTY 0x0002 * DMA_DONE 0x0001 * * It is called to enable/disable hardware interrupts. * PARAMETERS * IN IMpegEncoder* pIMpegEncoder - pointer to the decoder object * IN DWORD IrqMask - combination of flags mentioned above * SEE ALSO * IMpegEncoder_GetCurrentIrqMask/********************************************************************************************/void Csm2288__SetCurrentIrqMask(IMpegEncoder* pIMpegEncoder, DWORD IrqMask){ Csm2288* this = (Csm2288*) pIMpegEncoder; this->CurrentIrqMask = IrqMask; Csm2288__Write(pIMpegEncoder, SM2288_INT_EN_CTRL, IrqMask);}/****f* HwLib/IMpegEncoder_GetCurrentIrqMask * USAGE * DWORD IMpegEncoder_GetCurrentIrqMask(IMpegEncoder* pIMpegEncoder) * DWORD Csm2288__GetCurrentIrqMask(IMpegEncoder* pIMpegEncoder) * PARAMETERS * IN IMpegEncoder* pIMpegEncoder - pointer to the decoder object * RETURN VALUE * returns "CurrentIrqMask" variable previously set by IMpegEncoder_SetCurrentIrqMask * SEE ALSO * IMpegEncoder_SetCurrentIrqMask/********************************************************************************************/DWORD Csm2288__GetCurrentIrqMask(IMpegEncoder* pIMpegEncoder){ Csm2288* this = (Csm2288*) pIMpegEncoder; return this->CurrentIrqMask;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -