📄 es1371.cpp
字号:
}
return ulReadData;
}
// {{{ HwRegRMW
/* ----------------------------------------------------------------------- /
Routine: HwRegRMW
Purpose: The routine is used to access a Concert chip register via
its shadowed value. This routine is required to provide
exclusion (synchronization) to the register.
This routine should be run from the KeSynchronizeExecution
call, forceing this routine to execute at our devices
DIRQL. It also acquires the spin lock, providing exclusion.
The current value in the shadow ram is read, ANDed with
the mask and ORed with the bits.
Inputs:
Output: None
Errors: None
/ ----------------------------------------------------------------------- */
UCHAR
CES1371::HwRegRMW ( UCHAR Reg, UCHAR bBitMask, UCHAR bSetBits )
{
UCHAR bNewValue;
UCHAR *puc_DRegs = (UCHAR *)m_ulDRegs;
// are we setting the whole data space?
if ( 0x00 == bBitMask )
{
return ( *(puc_DRegs + Reg) );
}
else if ( 0xff == bBitMask )
{
bNewValue = bSetBits;
}
else
{
// read original value,
// zero out bits of interest,
// set proper bits to one
if ( (0xff != *(puc_DRegs + Reg)) || ( m_ulPowerState > 0 ) )
bNewValue = *(puc_DRegs + Reg);
else
bNewValue = READ_PORT_UCHAR (m_pPciAddr + Reg);
bNewValue &= ~bBitMask;
bNewValue |= (bSetBits & bBitMask);
}
// write new value to hardware
if ( 0 == m_ulPowerState )
WRITE_PORT_UCHAR ( m_pPciAddr + Reg, bNewValue);
// save the value for the future
*(puc_DRegs + Reg) = bNewValue;
return bNewValue;
} // end of function: hw_reg_rmw_char
// }}}
// {{{ HwRegRMW
USHORT
CES1371::HwRegRMW ( UCHAR Reg, USHORT wBitMask, USHORT wSetBits )
{
USHORT wNewValue;
USHORT *pus_DRegs = (USHORT *)m_ulDRegs;
// are we setting the whole data space?
if ( 0x0000 == wBitMask )
{
return ( *(pus_DRegs + Reg/2) );
}
else if ( 0xffff == wBitMask )
{
wNewValue = wSetBits;
}
else
{
// read original value,
// zero out bits of interest,
// set proper bits to one
if ( (0xffff != *(pus_DRegs + (Reg/2))) || ( m_ulPowerState > 0 ) )
wNewValue = *(pus_DRegs + (Reg/2));
else
wNewValue = READ_PORT_USHORT ( (PUSHORT)(m_pPciAddr + Reg) );
wNewValue &= ~wBitMask;
wNewValue |= (wSetBits & wBitMask);
}
/* write new value to hardware */
if ( 0 == m_ulPowerState )
WRITE_PORT_USHORT ( (PUSHORT)(m_pPciAddr + Reg), wNewValue );
// save the value for the future
*(pus_DRegs + (Reg/2)) = wNewValue;
return wNewValue;
} /* end of function: hw_reg_rmw_short */
// }}}
// {{{ HwRegRMW
ULONG
CES1371::HwRegRMW ( UCHAR Reg, ULONG dwBitMask, ULONG dwSetBits )
{
ULONG dwNewValue;
// are we setting the whole data space?
if ( 0x00000000 == dwBitMask )
{
return ( m_ulDRegs[Reg/4] );
}
else if ( 0xffffffff == dwBitMask )
{
dwNewValue = dwSetBits;
}
else
{
// read original value,
// zero out bits of interest,
// set proper bits to one
if ( (0xffffffff != m_ulDRegs[Reg/4]) || ( m_ulPowerState > 0 ) )
dwNewValue = m_ulDRegs[Reg/4];
else
dwNewValue = READ_PORT_ULONG ( (PULONG)(m_pPciAddr + Reg) );
dwNewValue &= ~dwBitMask;
dwNewValue |= (dwSetBits & dwBitMask);
}
/* write new value to hardware */
if ( 0 == m_ulPowerState )
WRITE_PORT_ULONG ( (PULONG)(m_pPciAddr + Reg), dwNewValue );
// save the value for the future
m_ulDRegs[Reg/4] = dwNewValue;
return dwNewValue;
} /* end of function: hw_reg_rmw_long */
// }}}
// {{{ SRCRegRead
USHORT
CES1371::SRCRegRead( USHORT reg )
{
/* LOCAL DATA */
ULONG dtemp;
/* END LOCAL DATA */
// Is the device powered down?
if ( m_ulPowerState > 0 )
return m_usSRCRegsPMContext[ reg ];
/* wait for ready */
dtemp = SRCPollIOReg ();
/* assert a read request */
WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
(dtemp & SRC_CTLMASK) | (ULONG(reg) << 25) );
/* wait for the data */
dtemp = SRCPollIOReg ();
return (USHORT) dtemp;
}
// }}}
void
CES1371::SRCRegWrite(USHORT reg, USHORT val)
{
ULONG i, dtemp;
// Is the device powered down?
if ( m_ulPowerState > 0 )
{
m_usSRCRegsPMContext[ reg ] = val;
return;
}
/* wait for ready */
dtemp = SRCPollIOReg ();
/* assert the write request */
i = (dtemp & SRC_CTLMASK) | SRC_WENABLE |
( (ULONG)reg << 25 ) | val;
/* write the value */
WRITE_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF), i);
#ifdef DBG
{
USHORT us;
us = SRCRegRead ( reg );
if ( us != val )
_DbgPrintF( DEBUGLVL_TERSE, ("[SRCRegWrite] FAILED reg %02x wrote %04x read %04x", reg, val, us));
}
#endif
return;
}
// }}}
void
CES1371::SRCSetRate( ULONG ulChannelIndex, USHORT wSampleRate )
{
ULONG i, freq, dtemp;
USHORT N, truncM, truncStart, wtemp;
// Is the device powered down?
if ( m_ulPowerState > 0 )
return;
switch ( ulChannelIndex )
{
case ES1371_DAC0:
// freeze the channel
for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
if( !(READ_PORT_ULONG ( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & SRC_BUSY) )
break;
dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF));
WRITE_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
(dtemp & SRC_CTLMASK) | SRC_DAC0FREEZE);
// calculate new frequency and write it
// preserve accum
freq = ((ULONG) wSampleRate << 16) / 3000U;
SRCRegWrite( SRC_DAC0_BASE + SRC_INT_REGS_OFF,
(SRCRegRead( SRC_DAC0_BASE + SRC_INT_REGS_OFF ) & 0x00ffU) |
((USHORT) (freq >> 6) & 0xfc00));
SRCRegWrite( SRC_DAC0_BASE + SRC_VFREQ_FRAC_OFF, (USHORT) freq >> 1);
// un-freeze the channel
for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
if( !(READ_PORT_ULONG ( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & SRC_BUSY) )
break;
dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF));
WRITE_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
(dtemp & SRC_CTLMASK) & (~SRC_DAC0FREEZE) );
break;
case ES1371_DAC1:
// freeze the channel
for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
if( !(READ_PORT_ULONG ( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & SRC_BUSY) )
break;
dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF));
WRITE_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
(dtemp & SRC_CTLMASK) | SRC_DAC1FREEZE);
// calculate new frequency and write it
// preserve accum
freq = ((ULONG) wSampleRate << 16) / 3000U;
SRCRegWrite( SRC_DAC1_BASE + SRC_INT_REGS_OFF,
(SRCRegRead( SRC_DAC1_BASE + SRC_INT_REGS_OFF ) & 0x00ffU) |
((USHORT) (freq >> 6) & 0xfc00));
SRCRegWrite( SRC_DAC1_BASE + SRC_VFREQ_FRAC_OFF, (USHORT) freq >> 1);
// un-freeze the channel
for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
if( !(READ_PORT_ULONG ( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & SRC_BUSY) )
break;
dtemp = READ_PORT_ULONG((PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF));
WRITE_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF),
(dtemp & SRC_CTLMASK) & (~SRC_DAC1FREEZE) );
break;
case ES1371_ADC:
// derive oversample ratio
N = wSampleRate/3000U;
if( N == 15 || N == 13 || N == 11 || N == 9 )
--N;
// truncate the filter and write n/trunc_start
truncM = (21*N - 1) | 1;
if( wSampleRate >= 24000U )
{
if( truncM > 239 )
truncM = 239;
truncStart = (239 - truncM) >> 1;
SRCRegWrite( SRC_ADC_BASE + SRC_TRUNC_N_OFF,
(truncStart << 9) | (N << 4));
}
else
{
if( truncM > 119 )
truncM = 119;
truncStart = (119 - truncM) >> 1;
SRCRegWrite( SRC_ADC_BASE + SRC_TRUNC_N_OFF,
0x8000U | (truncStart << 9) | (N << 4));
}
/* calculate new frequency and write it - preserve accum */
freq = ((48000UL << 16) / wSampleRate) * N;
wtemp = SRCRegRead( SRC_ADC_BASE + SRC_INT_REGS_OFF );
SRCRegWrite( SRC_ADC_BASE + SRC_INT_REGS_OFF,
(wtemp & 0x00ff) | ((USHORT) (freq >> 6) & 0xfc00));
SRCRegWrite( SRC_ADC_BASE + SRC_VFREQ_FRAC_OFF, (USHORT) freq >> 1);
SRCRegWrite( SRC_ADC_VOL_L, N << 8);
SRCRegWrite( SRC_ADC_VOL_R, N << 8);
break;
}
return;
}
//--------------------------------------------------------------------------
//
// Name: SRCWaitForFrame1
//
// Description: code that polls a value in the SRC converter so that we know
// when it is safe to write.
//
// Parameters: PFRAME_CONTEXT
//
// Returns: always succeeds
//
// Note: Apparently, we can't do CODEC writes when the sync pulse is high.
// Luckily, there are some debug things in the SRC that let us know
// when sync pulse is low. This needs to be synched with the ISR so
// we don't get interrupted and lose track of where we are.
//
//--------------------------------------------------------------------------
void
CES1371::SRCWaitForFrame1 ( )
{
while( !((READ_PORT_ULONG( (PULONG)(m_pPciAddr + ES1371_dSRCIO_OFF) ) & 0x00070000UL) ==
0x00010000UL) )
//<mod:ce> KeStallExecutionProcessor(1);
return;
}
// }}}
// {{{ SRCPollIOReg
//--------------------------------------------------------------------------
//
// Name: SRCPollIOReg
//
// Description:
//
// Parameters:
//
// Returns:
//
// Note: This function must be called prior to any
// writes to the Disable/Pause bits
//
//--------------------------------------------------------------------------
ULONG
CES1371::SRCPollIOReg ()
{
int i;
ULONG dw=0;
for (i=0; i<SRC_IOPOLL_COUNT; ++i)
{
if (!((dw = READ_PORT_ULONG ((PULONG)(m_pPciAddr+ES1371_dSRCIO_OFF))) & SRC_BUSY) )
break;
//<mod:ce> KeStallExecutionProcessor (1);
}
#ifdef DBG
if (i == SRC_IOPOLL_COUNT)
_DbgPrintF( DEBUGLVL_TERSE, ("[SRCPollIOReg] timeout %x", dw));
#endif
return dw;
}
// }}}
//--------------------------------------------------------------------------
//
// Name: InitDMAChannel
//
// Description: Intialize all the things about a DMA channel
//
// Parameters: ULONG ulChannelIndex : Index of the DMA channel to init
// ULONG ulBufferPhysAddr : Physical address of the DMA buffer
// in memory
// USHORT usBufferSize : Number of bytes in a DMA buffer
//
// Returns: none
//
// Note:
//
//--------------------------------------------------------------------------
void
CES1371::InitDMAChannel( ULONG ulChannelIndex, DMAINTHANDLER pfHandler, PVOID pContext)
{
m_dmachannel[ulChannelIndex].pfIntHandler = pfHandler;
m_dmachannel[ulChannelIndex].pvIntContext = pContext;
ULONG ulBufferPhysAddr = m_dmachannel[ulChannelIndex].ulBufferPhysAddr;
ULONG ulFrameCount = 0;
switch ( ulChannelIndex ) {
case ES1371_DAC0 :
// Set up the physical DMA buffer address
HwPagedIOWrite( ES1371_DAC0CTL_PAGE, ES1371_dDAC0PADDR_OFF, ulBufferPhysAddr);
// Clear out the Frame count register
HwPagedIOWrite( ES1371_DAC0CTL_PAGE, ES1371_wDAC0FC_OFF, ulFrameCount);
break;
case ES1371_DAC1 :
// Set up the physical DMA buffer address
HwPagedIOWrite( ES1371_DAC1CTL_PAGE, ES1371_dDAC1PADDR_OFF, ulBufferPhysAddr);
// Clear out the Frame count register
HwPagedIOWrite( ES1371_DAC1CTL_PAGE, ES1371_wDAC1FC_OFF, ulFrameCount);
break;
case ES1371_ADC :
// Set up the physical DMA buffer address
HwPagedIOWrite( ES1371_ADCCTL_PAGE, ES1371_dADCPADDR_OFF, ulBufferPhysAddr);
// Clear out the Frame count register
HwPagedIOWrite( ES1371_ADCCTL_PAGE, ES1371_wADCFC_OFF, ulFrameCount);
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -