📄 cem85xx.c
字号:
/********************************************************************************************//* cem85xx.c : Implementation of the EM85xx interface* REALmagic Quasar Hardware Library* Created by Aurelia Popa-Radu* Copyright Sigma Designs Inc* Sigma Designs Proprietary and confidential* Created on 05/17/02* Description:/********************************************************************************************/#include "pch.h"#if defined EM85XX_OBJECT// specific code for Jasper#include "cquasar.h"#include "em847x.h"#include "regs847x.h"#define CHIP_REVISION_REG 0x500008#define PIO_0F_INT_REG 0x500600#define PIO_0F_DATA_REG 0x500604#define PIO_0F_DIR_REG 0x500608#define PIO_0F_POL_REG 0x50060C#define PIO_0F_INT_EN_REG 0x500610#define PIO_101F_INT_REG 0x500A00#define PIO_101F_DATA_REG 0x500A04#define PIO_101F_DIR_REG 0x500A08#define PIO_101F_POL_REG 0x500A0C#define PIO_101F_INT_EN_REG 0x500A10QRESULT CEM85XX__SetPIODir(IDecoder* pIDecoder, DWORD PIONumber, DWORD Dir){ if(PIONumber < 16) { OSWritePciDword((DWORD *)PIO_0F_DIR_REG, ((Dir ? 0x00010001:0x00010000) << PIONumber)); } else { OSWritePciDword((DWORD *)PIO_101F_DIR_REG, ((Dir ? 0x00010001:0x00010000) << (PIONumber-16))); } return Q_OK;}QRESULT CEM85XX__WritePIO(IDecoder* pIDecoder, DWORD PIONumber, DWORD Data){ // don't assume that PIO is output if(PIONumber < 16) { OSWritePciDword((DWORD *)PIO_0F_DATA_REG, ((Data? 0x00010001:0x00010000) << PIONumber)); OSWritePciDword((DWORD *)PIO_0F_DIR_REG, (0x00010001 << PIONumber)); } else { OSWritePciDword((DWORD *)PIO_101F_DATA_REG, ((Data? 0x00010001:0x00010000) << (PIONumber-16))); OSWritePciDword((DWORD *)PIO_101F_DIR_REG, (0x00010001 << (PIONumber-16))); } return Q_OK;}QRESULT CEM85XX__ReadPIO(IDecoder* pIDecoder, DWORD PIONumber, DWORD* pData){ // don't assume that PIO is input if(PIONumber < 16) { OSWritePciDword((DWORD *)PIO_0F_DIR_REG, (0x00010000 << PIONumber) ); *pData = (OSReadPciDword((DWORD *)PIO_0F_DATA_REG) & (0x00000001 << PIONumber)) ? 1:0; } else { OSWritePciDword((DWORD *)PIO_101F_DIR_REG, (0x00010000 << (PIONumber-16)) ); *pData = (OSReadPciDword((DWORD *)PIO_101F_DATA_REG) & (0x00000001 << (PIONumber-16))) ? 1:0; } return Q_OK;}void CEM85XX__SetI2C_params(ISetI2CpIO* pISetI2CpIO, BYTE Data, BYTE Clock){ CQuasar* this = GET_CQUASAR_FROM_ISETI2CPIO (pISetI2CpIO); this->PIO_I2C_Data = Data; this->PIO_I2C_Clk = Clock; this->m_I2Cparams.m_dwData0 = 0x00010000 << Data; this->m_I2Cparams.m_dwData1 = 0x00010001 << Data; this->m_I2Cparams.m_dwDataIN = 0x00010000 << Data; this->m_I2Cparams.m_dwDataOUT = 0x00010001 << Data; this->m_I2Cparams.m_dwClock0 = 0x00010000 << Clock; this->m_I2Cparams.m_dwClock1 = 0x00010001 << Clock; this->m_I2Cparams.m_dwClkIN = 0x00010000 << Clock; this->m_I2Cparams.m_dwClkOUT = 0x00010001 << Clock;}void CEM85XX__SetClockDir(ISetI2CpIO* pISetI2CpIO, DWORD dir){ CQuasar* this = GET_CQUASAR_FROM_ISETI2CPIO (pISetI2CpIO); OSWritePciDword((DWORD *)PIO_0F_DIR_REG, dir);}void CEM85XX__SetDataDir(ISetI2CpIO* pISetI2CpIO, DWORD dir){ CQuasar* this = GET_CQUASAR_FROM_ISETI2CPIO (pISetI2CpIO); OSWritePciDword((DWORD *)PIO_0F_DIR_REG, dir);}void CEM85XX__WrClock(ISetI2CpIO* pISetI2CpIO, DWORD clock){ CQuasar* this = GET_CQUASAR_FROM_ISETI2CPIO (pISetI2CpIO); OSWritePciDword((DWORD *)PIO_0F_DATA_REG, clock);}void CEM85XX__WrData(ISetI2CpIO* ISetI2CpIO, DWORD data){ CQuasar* this = GET_CQUASAR_FROM_ISETI2CPIO (ISetI2CpIO); OSWritePciDword((DWORD *)PIO_0F_DATA_REG, data);}DWORD CEM85XX__RdData( ISetI2CpIO* ISetI2CpIO, DWORD Mask ){ CQuasar* this = GET_CQUASAR_FROM_ISETI2CPIO (ISetI2CpIO); DWORD Data = OSReadPciDword((DWORD *)PIO_0F_DATA_REG); if(Data & Mask) return 1; else return 0;}BOOL CEM85XX__WriteDramSlave(IDecoder* pIDecoder, IN DWORD addr, IN DWORD* pData, IN DWORD nBytes){ DWORD i, timeout; UCHAR* pBytes = (UCHAR*)pData; CheckTransferSize(nBytes, TEXT("WriteDramSlave")) CheckDramChannel(HOST_DRAM, TEXT("WriteDramSlave start timeout !")) ProgramDramChannel(HOST_DRAM, addr, nBytes) for(i=0; i<nBytes/4; i++) { OSWritePciDword((DWORD *)0x50150c, OSGetDword(pBytes) ); pBytes += 4; } switch(nBytes % 4) // write bytes that are not multiple of 4 { case 3: OSWritePciDword((DWORD *)0x501508,OSGetDword(pBytes)); break; case 2: OSWritePciDword((DWORD *)0x501504,OSGetDword(pBytes)); break; case 1: OSWritePciDword((DWORD *)0x501500,OSGetDword(pBytes)); default: break; } CheckDramChannel(HOST_DRAM, TEXT("WriteDramSlave end timeout !")) return TRUE;}BOOL CEM85XX__FillDramSlave(IDecoder* pIDecoder, IN DWORD addr,IN DWORD nBytes, DWORD value){ DWORD i,timeout; CheckTransferSize(nBytes, TEXT("FillDramSlave")) CheckDramChannel(HOST_DRAM, TEXT("FillDramSlave start timeout !")) ProgramDramChannel(HOST_DRAM, addr, nBytes) for(i=0; i<nBytes/4; i++) OSWritePciDword((DWORD *)0x50150c, value ); switch(nBytes % 4) { case 3: OSWritePciDword((DWORD *)0x501508, value); break; case 2: OSWritePciDword((DWORD *)0x501504, value); break; case 1: OSWritePciDword((DWORD *)0x501500, value); default: break; } CheckDramChannel(HOST_DRAM, TEXT("FillDramSlave end timeout !")) return TRUE;}BOOL CEM85XX__ReadSlaveDramToHost(IDecoder* pIDecoder, IN DWORD addr, OUT DWORD* pData, IN DWORD nBytes){ UCHAR* pBytes = (UCHAR*)pData; DWORD i, timeout; volatile DWORD tmp; // BUGFIX: Hack to fix a bug in EM8500 - Consecutive read access to slave channel // will fails, so we read a register in another block before reading the slave // data register.(see BUGFIX lines below) // Beware of compiler optimizations (gcc is happy with volatile declaration) // (Ask sammy for details..) -- Fabrice 06/25/02 CheckTransferSize(nBytes, TEXT("ReadDramSlave")) CheckDramChannel(DRAM_HOST, TEXT("ReadDramSlave start timeout !")) // select Port1 for Slave Write to Host CQuasar__WriteReg(pIDecoder, QPM_to_host_master_ena, Port1_to_SlaveWriteToHost); ProgramDramChannel(DRAM_HOST, addr, nBytes) for(i=0; i<nBytes/4; i++) { tmp = OSReadPciDword((DWORD *)0x500000); // BUGFIX OSPutDword(OSReadPciDword((DWORD *)0x50150c), pBytes); pBytes += 4; } switch(nBytes % 4) { case 3: tmp = OSReadPciDword((DWORD *)0x500000); // BUGFIX OSPutDword(OSReadPciDword((DWORD *)0x501508), pBytes); break; case 2: tmp = OSReadPciDword((DWORD *)0x500000); // BUGFIX OSPutDword(OSReadPciDword((DWORD *)0x501504), pBytes); break; case 1: tmp = OSReadPciDword((DWORD *)0x500000); // BUGFIX OSPutDword(OSReadPciDword((DWORD *)0x501500), pBytes); default: break; } CheckDramChannel(DRAM_HOST, TEXT("ReadDramSlave end timeout !")) return TRUE;}///////////////////////////////////////////////////////////////////////////// start I2C specific implementation#include "ci2c.h"static void EM85xx_WriteReg (DWORD Reg, DWORD Data){ *((volatile DWORD *)Reg) = Data;}static DWORD EM85xx_ReadReg (DWORD Reg){ return *((volatile DWORD *)(Reg));}#define I2C_MASTER_BASE_ADDRESS (0x500800)#define I2C_MASTER_CONFIG (I2C_MASTER_BASE_ADDRESS + 0x00)#define I2C_MASTER_CLK_DIV (I2C_MASTER_BASE_ADDRESS + 0x04)#define I2C_MASTER_DEV_ADDR (I2C_MASTER_BASE_ADDRESS + 0x08)#define I2C_MASTER_ADR (I2C_MASTER_BASE_ADDRESS + 0x0c)#define I2C_MASTER_DATAOUT (I2C_MASTER_BASE_ADDRESS + 0x10)#define I2C_MASTER_DATAIN (I2C_MASTER_BASE_ADDRESS + 0x14)#define I2C_MASTER_STATUS (I2C_MASTER_BASE_ADDRESS + 0x18)#define I2C_MASTER_STARTXFER (I2C_MASTER_BASE_ADDRESS + 0x1c)#define I2C_MASTER_BYTE_CNT (I2C_MASTER_BASE_ADDRESS + 0x20)#define I2C_MASTER_INTEN (I2C_MASTER_BASE_ADDRESS + 0x24)#define I2C_MASTER_INT (I2C_MASTER_BASE_ADDRESS + 0x28)void CEM85xxI2C__Init ( II2C* pII2C ){}BOOL CEM85xxI2C__Write( II2C* pII2C, BYTE adr, BYTE* pData, int n ){ CI2C *this = (CI2C*) pII2C ; int i; EM85xx_WriteReg (I2C_MASTER_CONFIG, 0xf8); EM85xx_WriteReg (I2C_MASTER_CLK_DIV, 375); // assume 150mhz clock // XXX bug: 0x70 is hardcoded as the device address EM85xx_WriteReg (I2C_MASTER_DEV_ADDR, this->m_bI2cWriteAddr >> 1); // ready for a command // XXX bug: we really should have a timeout here while ((EM85xx_ReadReg (I2C_MASTER_STATUS) & 1) == 0); // write for (i=0; i<n; i++) { EM85xx_WriteReg (I2C_MASTER_ADR, adr++); EM85xx_WriteReg (I2C_MASTER_BYTE_CNT, 0); EM85xx_WriteReg (I2C_MASTER_DATAOUT, *pData++); EM85xx_WriteReg (I2C_MASTER_STARTXFER, 0); // XXX bug: we really should have a timeout here while ((EM85xx_ReadReg (I2C_MASTER_STATUS) & 2) == 0); } return TRUE;}BOOL CEM85xxI2C__Read( II2C* pII2C, BYTE adr, BYTE* pData, int n ){ CI2C *this = (CI2C*) pII2C ; int i; EM85xx_WriteReg (I2C_MASTER_CLK_DIV, 375); // assume 150mhz clock 375=750/2 // ready for a command // XXX bug: we really should have a timeout here while ((EM85xx_ReadReg (I2C_MASTER_STATUS) & 1) == 0); for (i=0; i<n; i++) { EM85xx_WriteReg (I2C_MASTER_CONFIG, 0xfa); EM85xx_WriteReg (I2C_MASTER_BYTE_CNT, 0); // XXX bug: 0x70 is hardcoded as the device address ??? EM85xx_WriteReg (I2C_MASTER_DEV_ADDR, this->m_bI2cReadAddr >> 1); EM85xx_WriteReg (I2C_MASTER_DATAOUT, adr++); EM85xx_WriteReg (I2C_MASTER_STARTXFER, 0); // XXX bug: we really should have a timeout here while ((EM85xx_ReadReg (I2C_MASTER_STATUS) & 2) == 0); while ((EM85xx_ReadReg (I2C_MASTER_STATUS) & 1) == 0); EM85xx_WriteReg (I2C_MASTER_CONFIG, 0x00FA); EM85xx_WriteReg (I2C_MASTER_BYTE_CNT, 0); // XXX bug: 0x70 is hardcoded as the device address EM85xx_WriteReg (I2C_MASTER_DEV_ADDR, this->m_bI2cReadAddr >> 1); EM85xx_WriteReg (I2C_MASTER_STARTXFER, 1); // XXX bug: we really should have a timeout here while ((EM85xx_ReadReg (I2C_MASTER_STATUS) & 4) == 0); while ((EM85xx_ReadReg (I2C_MASTER_STATUS) & 1) == 0); *pData++ = (BYTE)EM85xx_ReadReg (I2C_MASTER_DATAIN); } return TRUE;}BOOL CEM85xxI2C__Write_NoSubAddr( II2C* pII2C, BYTE* pData, int n ){ // XXX bug: implement to use TvTuner return TRUE;}BOOL CEM85xxI2C__Read_NoSubAddr( II2C* pII2C, BYTE* pData, int n ){ // XXX bug: implement to use TvTuner return TRUE;}// end I2C specific implementation///////////////////////////////////////////////////////////////////////////#ifdef UCODE_ROM_ADDRESS#warning using external ucodeUCHAR *UCodeJasper;#elseUCHAR UCodeJasper[] = { #ifdef MICROCODE_NO_DOLBY #include "jasper/tst_no_dolby.h" // doesn't play dolby no matter the bonding of the chip #else #include "jasper/tst.h" // play dolby no matter the bonding of the chip #endif};#endif/****v* HwLib/J * NAME * J * DESCRIPTION * Global array of symbols used to send commands and data to EM847x through microcode./********************************************************************************************/JSymbolTable J;#undef DEFINE_ENTRY#define DEFINE_ENTRY(Symbol) J.Symbol.str = #Symbol;#include "symbols.h"QRESULT InitializeJSymbolsTable( IDecoder* pIDecoder ){ // same symbols like EM847X except VideoIn SymbolEntry* pSymbolEntry = (SymbolEntry*)&J; int i; CommonSymbols Q4Mpeg4SymbolsTable Q4AudioNewSymbolsTable Q4ReverseGOPSymbolsTable VideoCaptureSymbolTable JOSDSymbolsTable for( i=0;i<( sizeof(JSymbolTable)/sizeof(SymbolEntry) );i++ ) { if( !CQuasar__SearchSymbol(pIDecoder, pSymbolEntry->str, &pSymbolEntry->addr)) { pSymbolEntry->addr = 0; OSsprintf(g_InfoError, TEXT("Symbol %s not found"), pSymbolEntry->str ); QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("Symbol %s not found"), pSymbolEntry->str)); return E_GET_SYMBOLS_FAILED; } pSymbolEntry++; } return Q_OK;}QRESULT CEM85XX__SetMicrocode(IDecoder* pIDecoder, DWORD Id){ CQuasar *this = (CQuasar*) pIDecoder; if(Id == ebiUcode_MpegDecode) {#ifndef UCODE_ROM_ADDRESS this->pUCode = (BYTE*)UCodeJasper; this->UCodeSize = sizeof(UCodeJasper);#else#warning using external ucode // special uCode in ROM this->UCodeSize = *(DWORD *)(UCODE_ROM_ADDRESS); this->pUCode = OSmalloc(this->UCodeSize); QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("Setting ucode %p - %08x"), UCODE_ROM_ADDRESS+4,this->UCodeSize)); OSmemcpy(this->pUCode, UCODE_ROM_ADDRESS+4,this->UCodeSize); #endif this->pQ = (void*)&J; this->SymbolTableSize = sizeof(J); return InitializeJSymbolsTable(pIDecoder); } else return E_NOT_SUPPORTED;}void CEM85XX__InitVtable(IDecoder* pIDecoder){ unsigned long int ChipRevision; CQuasar *this = (CQuasar*) pIDecoder; ChipRevision = OSReadPciDword ((DWORD *)CHIP_REVISION_REG); this->VTable.InitPtsFifo = CEM847X__InitPtsFifo; this->VTable.PtsFifoEmptiness = CEM847X__PtsFifoEmptiness; this->VTable.WritePTS = CEM847X__WritePTS; this->VTable.WritePCR = CEM847X__WritePCR; this->VTable.SetAudioSampleRate = CEM847X__SetAudioSampleRate; // revision 1 and above has an "enhanced" audio clock if (ChipRevision) this->VTable.SetAudioSampleRate = CEM848X__SetAudioSampleRate; else this->VTable.SetAudioSampleRate = CEM847X__SetAudioSampleRate; this->VTable.InitPropertySet = CEM847X__InitPropertySet; this->VTable.SetProperty = CEM847X__SetProperty; this->VTable.GetProperty = CEM847X__GetProperty; this->VTable.SetDisplayFilter = CEM847X__SetDisplayFilter; this->VTable.ProgramVClk = CEM847X__ProgramVClk; this->VTable.ReadLbcReg = CEM847X__ReadLbcReg; this->VTable.WriteLbcReg = CEM847X__WriteLbcReg; this->VTable.WriteDataToLBC = CEM847X__WriteDataToLBC; this->VTable.ReadDataFromLBC = CEM847X__ReadDataFromLBC; this->VTable.SetMicrocode = CEM85XX__SetMicrocode; this->VTable.SetPIODir = CEM85XX__SetPIODir; this->VTable.WritePIO = CEM85XX__WritePIO; this->VTable.ReadPIO = CEM85XX__ReadPIO; this->VTable.WriteDramSlave = CEM85XX__WriteDramSlave; this->VTable.FillDramSlave = CEM85XX__FillDramSlave; this->VTable.ReadDramSlave = CEM85XX__ReadSlaveDramToHost; this->m_ISetI2CpIOVtbl.SetI2C_params = CEM85XX__SetI2C_params; this->m_ISetI2CpIOVtbl.SetClockDir = CEM85XX__SetClockDir; this->m_ISetI2CpIOVtbl.SetDataDir = CEM85XX__SetDataDir; this->m_ISetI2CpIOVtbl.WrClock = CEM85XX__WrClock; this->m_ISetI2CpIOVtbl.WrData = CEM85XX__WrData; this->m_ISetI2CpIOVtbl.RdData = CEM85XX__RdData;}void CQuasar__InitVtable(IDecoder* pIDecoder){ CEM85XX__InitVtable(pIDecoder);}void CSigmaTv__InitVtable(ITvEncoder* pITvEncoder){ CEM847X__TvInitVtable(pITvEncoder);}#endif // EM85XX_OBJECT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -