📄 cem847x.c
字号:
} else break; } while (1) { if ( (numerator<0x10000) && ((denominator - numerator)<0x10000) ) break; if (((numerator % 3) == 0) && ((denominator % 3) == 0)) { numerator = numerator / 3; denominator = denominator / 3; } else break; } while (1) { if ( (numerator<0x10000) && ((denominator - numerator)<0x10000) ) break; if (((numerator % 5) == 0) && ((denominator % 5) == 0)) { numerator = numerator / 5; denominator = denominator / 5; } else break; } // Divide by 7 as well? What about 13, 17, 19, 23 ... if( (numerator<0x10000) && ((denominator - numerator)<0x10000) ) { // multiply back to 3,2 to make sure I get the greatest m, n possible, // to decrease the ppm variation for VCXO while (1) { if( ((numerator*3)<0x10000) && (((denominator - numerator)*3)<0x10000) ) { numerator = numerator * 3; denominator = denominator * 3; } else break; } while (1) { if( ((numerator*2)<0x10000) && (((denominator - numerator)*2)<0x10000) ) { numerator = numerator * 2; denominator = denominator * 2; } else break; } *pm = numerator; *pn = denominator - numerator; return TRUE; } else return FALSE;}QRESULT CEM848X__SetAudioSampleRate(IDecoder* pIDecoder, DWORD Rate){ CQuasar *this = (CQuasar*) pIDecoder; Q4SymbolTable* pQ4 = (Q4SymbolTable*)this->pQ; DWORD n,m; this->CurrentAudioRate = Rate; QDbgLog((QLOG_TRACE, QDebugLevelWarning, TEXT(" CEM848X__SetAudioSampleRate=%lu"), Rate)); // In 848x ACLK256 is obtained from Fin using next formula: // Aclk256 = Fin * m/(2*(m+n)), where Fin can be mclk or Damck, // m is Jda1_setup_lo symbol -> 0x1FDD register // n is Jda1_setup_hi symbol -> 0x1FDE register if( this->QuasarVersion == EM85XX_JASPER ) { this->AudioSampleRateSupport_96kHz = 0; if(Rate > 48000) Rate /= 2; // 512*Rate/RISC_Clock = m/(m+n) if( !FindDividerCoef( 512*Rate, this->RISC_Clock, &n, &m) ) return Q_FAIL; QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" FindDividerCoef SampleRate=%d m=%d, n=%d"), OSDDiv(this->RISC_Clock, m, 512*(m+n)), m, n )); } else { // 512*Rate/MClock = m/(m+n) if( !FindDividerCoef( 512*Rate, this->DramFreq, &n, &m) ) return Q_FAIL; QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" FindDividerCoef SampleRate=%d m=%d, n=%d"), OSDDiv(this->DramFreq, m, 512*(m+n)), m, n )); } if( this->AudioSampleRateSupport_96kHz ) { this->ChannelStatus = (this->ChannelStatus & ~Q3_ASpdifStat1_rate) | ((Rate==32000) ? Q3_ASpdifStat1_32k : ((Rate==44100) ? Q3_ASpdifStat1_44k : ((Rate==88200) ? Q3_ASpdifStat1_88k : ((Rate==96000) ? Q3_ASpdifStat1_96k : Q3_ASpdifStat1_48k)))); } else { this->ChannelStatus = (this->ChannelStatus & ~Q3_ASpdifStat1_rate) | (((Rate==32000) || (Rate==64000)) ? Q3_ASpdifStat1_32k : (((Rate==44100) || (Rate==88200)) ? Q3_ASpdifStat1_44k : Q3_ASpdifStat1_48k)); } //ccc force the microcode to update the new settings CQuasar__WriteDM(pIDecoder, pQ4->Jda1_setup_lo.addr, n); CQuasar__WriteDM(pIDecoder, pQ4->Jda1_setup_hi.addr, m); CQuasar__WriteReg(pIDecoder, AUDIO_jda1_setup_lo, n); CQuasar__WriteReg(pIDecoder, AUDIO_jda1_setup_hi, m); CQuasar__WriteReg(pIDecoder, AUDIO_spdif_chstat1, HIWORD(this->ChannelStatus)); return Q_OK;}/****f* HwLib/IDecoder_WriteLbcReg * USAGE * QRESULT IDecoder_WriteLbcReg(IDecoder* pIDecoder, DWORD Address, DWORD Data) * QRESULT CEM847X__WriteLbcReg(IDecoder* pIDecoder, DWORD Address, DWORD Data) * PARAMETERS * IN IDecoder* pIDecoder - pointer to the Decoder object * IN DWORD Address - address of the register to write * IN DWORD Data - data to write/********************************************************************************************/QRESULT CEM847X__WriteLbcReg(IDecoder* pIDecoder, DWORD Address, DWORD Data){ // CQuasar* this = (CQuasar*) pIDecoder; DWORD timeout = 25; while( --timeout && (IDecoder_ReadReg(pIDecoder, LBC_status_reg) & 0x0002) ); if(timeout == 0) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" WriteLbcReg at %x BUSY"), Address )); IDecoder_WriteReg(pIDecoder, LBC_status_reg, 0xA0);// clear error enable the timeout return Q_FAIL; } IDecoder_WriteReg(pIDecoder, LBC_write_reg_addr, Address); IDecoder_WriteReg(pIDecoder, LBC_write_reg_data, Data); QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" WriteLbcReg at %x = %x"), Address, Data)); return Q_OK;}/****f* HwLib/IDecoder_ReadLbcReg * USAGE * QRESULT IDecoder_ReadLbcReg(IDecoder* pIDecoder, DWORD Address, DWORD* pData) * QRESULT CEM847X__ReadLbcReg(IDecoder* pIDecoder, DWORD Address, DWORD* pData) * PARAMETERS * IN IDecoder* pIDecoder - pointer to the Decoder object/********************************************************************************************/QRESULT CEM847X__ReadLbcReg(IDecoder* pIDecoder, DWORD Address, DWORD* pData){ // CQuasar* this = (CQuasar*) pIDecoder; DWORD timeout = 25; while( --timeout && (IDecoder_ReadReg(pIDecoder, LBC_status_reg) & 0x0001) ); if(timeout == 0) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" ReadLbcRegA at %x BUSY"), Address )); IDecoder_WriteReg(pIDecoder, LBC_status_reg, 0xA0);// clear error enable the timeout return Q_FAIL; } IDecoder_WriteReg(pIDecoder, LBC_read_reg_addr, Address); timeout = 25; while( --timeout && (IDecoder_ReadReg(pIDecoder, LBC_status_reg) & 0x0001) ); if(timeout == 0) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" ReadLbcRegD at %x BUSY"), Address )); IDecoder_WriteReg(pIDecoder, LBC_status_reg, 0xA0);// clear error enable the timeout return Q_FAIL; } *pData = IDecoder_ReadReg(pIDecoder, LBC_read_reg_data); QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" ReadLbcReg at %x = %x"), Address, *pData)); return Q_OK;}/****f* HwLib/CEM847X__ReadDataFromLBC * USAGE * QRESULT IDecoder_ReadDataFromLBC(IDecoder* pIDecoder, IN DWORD PhysAddr, IN DWORD nBytes) * QRESULT CQuasar__ReadDataFromLBC(IDecoder* pIDecoder, IN DWORD PhysAddr, IN DWORD nBytes) * DESCRIPTION * CEM840X__ReadDataFromLBC programs EM847x to receive "nBytes" bytes from LBC * and to write the data in host memory using PCI bus master. PhysAddr must point to a physical * contiguous buffer of nBytes, otherwise the system hangs. * "nBytes" can be any value multiple of 4 between 16 and 0xFFFF. * PARAMETERS * IN IDecoder* pIDecoder - pointer to the decoder object * IN DWORD Type - * - bits 0,1 describing the interface(LBC_config_LG, LBC_config_LG, LBC_config_Sm2288) * - bit 2 - LBC_config_swap_bytes * - bits 5,6,7 describing the delay (LBC_config_delay_0,...LBC_config_delay_4) * - bits 16..23 describing the path of the transfer (LRCH0_Port1_HostMaster,...Dram_CHR0_LWCH0_Ucode) * * IN DWORD Addr - physical address of the system buffer to write * IN DWORD nBytes - number of bytes to transfer * SEE ALSO * IDecoder_WriteDramSlave/********************************************************************************************/QRESULT CEM847X__ReadDataFromLBC(IDecoder* pIDecoder, IN DWORD Type, IN DWORD Addr, IN DWORD nBytes){ DWORD temp; if( (nBytes < 0x10) || (nBytes > 0xFFFF) || ( nBytes%4 )) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("CQuasar__ReadDataFromLBC Cannot transfer 0x%x!"), nBytes)); return Q_FAIL; } switch(Type & 0x00FF0000){ case LRCH0_Port2_HostMaster: if( CQuasar__ReadReg(pIDecoder, QPM_to_host_xfer_cnt) ) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("CQuasar__ReadDataFromLBC busy xcnt= 0x%x, clear it !"), CQuasar__ReadReg(pIDecoder, QPM_to_host_xfer_cnt) )); CQuasar__WriteReg(pIDecoder, QPM_to_host_xfer_cnt, 0); // do not make this fatal. Try to go on // It has proved to be ok in all cases (Emmanuel) // return Q_FAIL; } // any DRAM_portmux should be OK for this type of transfer // select Port2 for Master Write to Host CQuasar__WriteReg(pIDecoder, QPM_to_host_master_ena, Port2_to_MasterWriteToHost); CQuasar__WriteReg(pIDecoder, QPM_master_xfer_enable, 1); CQuasar__WriteReg(pIDecoder, QPM_to_host_addr_lo, Addr & 0xFFFF); CQuasar__WriteReg(pIDecoder, QPM_to_host_addr_hi, Addr >> 16); CQuasar__WriteReg(pIDecoder, QPM_to_host_xfer_cnt, nBytes); // connect LRCH0 to Port2 and ask LRCH0 to receive the data from LBC temp = CQuasar__ReadReg(pIDecoder, LBC_config) & 0xe200; CQuasar__WriteReg(pIDecoder, LBC_config, temp | LBC_config_LRCH0_to_Port2 | LOBYTE(Type) ); CQuasar__WriteReg(pIDecoder, LBC_read_fifo0_access, 0x8000);// SM2288_DRAM_DATA CQuasar__WriteReg(pIDecoder, LBC_read_fifo0_cnt, nBytes); return Q_OK; case LRCH0_Port1_HostMaster: if( CQuasar__ReadReg(pIDecoder, QPM_to_host_xfer_cnt) ) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("CQuasar__ReadDataFromLBC busy xcnt= 0x%x, clear it !"), CQuasar__ReadReg(pIDecoder, QPM_to_host_xfer_cnt) )); CQuasar__WriteReg(pIDecoder, QPM_to_host_xfer_cnt, 0); // do not make this fatal. Try to go on // It has proved to be ok in all cases (Emmanuel) // return Q_FAIL; } // any DRAM_portmux should be OK for this type of transfer // select Port1 for Master Write to Host CQuasar__WriteReg(pIDecoder, QPM_to_host_master_ena, Port1_to_MasterWriteToHost); CQuasar__WriteReg(pIDecoder, QPM_to_host_addr_lo, Addr & 0xFFFF); CQuasar__WriteReg(pIDecoder, QPM_to_host_addr_hi, Addr >> 16); CQuasar__WriteReg(pIDecoder, QPM_to_host_xfer_cnt, nBytes); // connect LRCH0 to Port2 and ask LRCH0 to receive the data from LBC temp = CQuasar__ReadReg(pIDecoder, LBC_config) & 0xe200; CQuasar__WriteReg(pIDecoder, LBC_config, temp | LBC_config_LRCH0_to_Port1 | LOBYTE(Type) ); CQuasar__WriteReg(pIDecoder, LBC_read_fifo0_access, 0x8000);// SM2288_DRAM_DATA CQuasar__WriteReg(pIDecoder, LBC_read_fifo0_cnt, nBytes); return Q_OK; default: break; } return Q_FAIL;}/****f* HwLib/CQuasar__WriteDataToLBC * USAGE * QRESULT IDecoder_WriteDataToLBC(IDecoder* pIDecoder, IN DWORD PhysAddr, IN DWORD nBytes) * QRESULT CQuasar__WriteDataToLBC(IDecoder* pIDecoder, IN DWORD PhysAddr, IN DWORD nBytes) * DESCRIPTION * CQuasar__WriteDataToLBC programs EM847x to receive "nBytes" bytes from LBC * and to write the data in host memory using PCI bus master. PhysAddr must point to a physical * contiguous buffer of nBytes, otherwise the system hangs. * "nBytes" can be any value multiple of 4 between 16 and 0xFFFF. * PARAMETERS * IN IDecoder* pIDecoder - pointer to the decoder object * IN DWORD Type - * IN DWORD Addr - physical address of the system buffer to write * IN DWORD nBytes - number of bytes to transfer * SEE ALSO * IDecoder_WriteDramSlave/********************************************************************************************/QRESULT CEM847X__WriteDataToLBC(IDecoder* pIDecoder, IN DWORD Type, IN DWORD Addr, IN DWORD nBytes){ DWORD temp; if( (nBytes < 0x8) || (nBytes > 0xFFFF) || ( nBytes%4 )) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("CQuasar__WriteDataToLBC Cannot transfer 0x%x!"), nBytes)); return Q_FAIL; } if ( ((Type & 0x00FF0000) == HostMaster_W4_LWCH0_Dram) ||((Type & 0x00FF0000) == HostMaster_W4_LWCH0_Ucode) ) { if( CQuasar__ReadReg(pIDecoder, QPM_from_host_xfer_cnt) ) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("CQuasar__WriteDataToLBC busy = 0x%x !"), CQuasar__ReadReg(pIDecoder, QPM_from_host_xfer_cnt) )); return Q_FAIL; } // connect PCI master to W4 and PCI slave to W0 OK for VideoIn CQuasar__WriteReg(pIDecoder, 0x1fe5, 4); CQuasar__WriteReg(pIDecoder, 0x1fe6, 5); // connect W4 to LWCH0 temp = CQuasar__ReadReg(pIDecoder, LBC_config) & 0xfc00; CQuasar__WriteReg(pIDecoder, LBC_config, temp | LBC_config_LWCH0_to_W4 | LOBYTE(Type) ); // ask LWCH0 to send data to stream machine if ((Type & 0x00FF0000) == HostMaster_W4_LWCH0_Ucode) CQuasar__WriteReg(pIDecoder, LBC_write_fifo0_access, 0x001c);// SM2288_UCODE_DOWNLOAD else CQuasar__WriteReg(pIDecoder, LBC_write_fifo0_access, 0x8000);// SM2288_DRAM_DATA CQuasar__WriteReg(pIDecoder, LBC_write_fifo0_cnt, nBytes); // Set up PCI master to read from system memory CQuasar__WriteReg(pIDecoder, QPM_from_host_addr_lo, Addr & 0xFFFF); CQuasar__WriteReg(pIDecoder, QPM_from_host_addr_hi, Addr >> 16); CQuasar__WriteReg(pIDecoder, QPM_from_host_xfer_cnt, nBytes); CQuasar__WriteReg(pIDecoder, QPM_xfer_reverse, 0); CQuasar__WriteReg(pIDecoder, QPM_master_xfer_enable, 1); return Q_OK; } else if( ((Type & 0x00FF0000) == Dram_CHR0_LWCH0_Dram) ||((Type & 0x00FF0000) == Dram_CHR0_LWCH0_Ucode) ) { if( CQuasar__ReadReg(pIDecoder, DRAM_zcnt(RD0)) ) { QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("CQuasar__WriteDataToLBC busy = 0x%x !"), CQuasar__ReadReg(pIDecoder, DRAM_xcnt(RD0)) )); return Q_FAIL; } IDecoder_WriteReg(pIDecoder, DRAM_portmux, (IDecoder_ReadReg(pIDecoder, DRAM_portmux) & ~DRAM_portmux_CHR0_Mask) | DRAM_portmux_CHR0_to_LWCH0); // connect R0a to LWCH0 temp = CQuasar__ReadReg(pIDecoder, LBC_config) & 0xfc00; CQuasar__WriteReg(pIDecoder, LBC_config, temp | LBC_config_LWCH0_to_R0a | LOBYTE(Type) ); // ask LWCH0 to send data to stream machine if ((Type & 0x00FF0000) == Dram_CHR0_LWCH0_Ucode) CQuasar__WriteReg(pIDecoder, LBC_write_fifo0_access, 0x1c);// SM2288_UCODE_DOWNLOAD else CQuasar__WriteReg(pIDecoder, LBC_write_fifo0_access, 0x8000);// SM2288_DRAM_DATA CQuasar__WriteReg(pIDecoder, LBC_write_fifo0_cnt, nBytes); ProgramDramChannel(RD0, Addr, nBytes)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -