⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 es1371.cpp

📁 此代码为WCE5.0下声卡的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
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( UCHAR ucDMAChannel, USHORT wSampleRate )
{
    ULONG    i, freq, dtemp;
    USHORT   N, truncM, truncStart, wtemp;

    // Is the device powered down?
    if ( m_ulPowerState > 0 )
        return;

    switch ( ucDMAChannel )
    {
      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: UCHAR ucDMAChannel : Index of the DMA channel to init
//              ULONG ulPhysDMAAddr : Physical address of the DMA buffer
//                                    in memory
//              USHORT usBufferSize : Number of bytes in a DMA buffer
//
//  Returns: none   
//
//  Note:
//
//--------------------------------------------------------------------------
void
CES1371::InitDMAChannel( UCHAR ucDMAChannel,
                         ULONG ulPhysDMAAddr,
                         ULONG ulBufferSize )
{
  ULONG ulFrameCount = 0;

  m_dmachannel[ucDMAChannel].ulPhysDMAAddr = ulPhysDMAAddr;
  m_dmachannel[ucDMAChannel].ulDMABufSize  = ulBufferSize;

  switch ( ucDMAChannel )
  {
    case ES1371_DAC0 :
      // Set up the physical DMA buffer address
      HwPagedIOWrite( ES1371_DAC0CTL_PAGE, ES1371_dDAC0PADDR_OFF, ulPhysDMAAddr);  
      // 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, ulPhysDMAAddr);  
      // 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, ulPhysDMAAddr);  
      // Clear out the Frame count register
      HwPagedIOWrite( ES1371_ADCCTL_PAGE, ES1371_wADCFC_OFF, ulFrameCount);  
      break;
  }
  return ;
}  

//--------------------------------------------------------------------------
//
//  Name: SetDMAChannelFormat
//
//  Description: Set the Format of a particular DMA channel.
//
//  Parameters: UCHAR ucDMAChannel : Index of the DMA channel to init
//              ULONG ulChannels   : Number of audio channels 1=mono 2=stereo
//              ULONG ul16Bit      : flag for sample size 0=8bit 1=16bit
//              ULONG ulSampleRate : actual number of samples/second.
//
//  Returns: none   
//
//  Note:
//
//--------------------------------------------------------------------------
void
CES1371::SetDMAChannelFormat( UCHAR ucDMAChannel,
                              ULONG ulChannels,
                              ULONG ul16Bit,
                              ULONG ulSampleRate )
{
  UCHAR ucFormatBits;
  UCHAR ucSkipCount;

  // save off the info for power managment
  m_dmachannel[ucDMAChannel].ulChannels   = ulChannels;
  m_dmachannel[ucDMAChannel].ul16Bit      = ul16Bit;
  m_dmachannel[ucDMAChannel].ulSampleRate = ulSampleRate;

  // first set the new sample rate
  SRCSetRate ( ucDMAChannel, (USHORT) ulSampleRate );

  switch ( ucDMAChannel )
  {
    case ES1371_DAC0 :
      // set format bits for DAC0 ... 
      ucFormatBits = 0x00;
      if( 2 == ulChannels )
          ucFormatBits |= ES1371_PCM_DAC0_STEREO ;
      if( 1 == ul16Bit )
          ucFormatBits |= ES1371_PCM_DAC0_16BIT ;

      HwRegRMW( ES1371_bSERFMT_OFF, 
                ES1371_PCM_DAC0_STEREO|ES1371_PCM_DAC0_16BIT,
                ucFormatBits ); 
      break;

    case ES1371_DAC1 :
      // set format bits for DAC1 ... 
      ucFormatBits = 0x00;
      if( 2 == ulChannels )
          ucFormatBits |= ES1371_PCM_DAC1_STEREO ;
      if( 1 == ul16Bit )
      {
          ucFormatBits |= ES1371_PCM_DAC1_16BIT ;
          // set the SKIP register for proper playback
          ucSkipCount = 0x10;
          HwRegRMW( ES1371_bSKIPC_OFF, 0x18, ucSkipCount ); 
      }
      else
      {   // set the SKIP register for proper playback
          ucSkipCount = 0x08;
          HwRegRMW( ES1371_bSKIPC_OFF, 0x18, ucSkipCount ); 
      }

      HwRegRMW( ES1371_bSERFMT_OFF, 
                ES1371_PCM_DAC1_STEREO|ES1371_PCM_DAC1_16BIT,
                ucFormatBits ); 
      break;

    case ES1371_ADC :
      // set format bits for ADC ... 
      ucFormatBits = 0x00;
      if( 2 == ulChannels )
          ucFormatBits |= ES1371_PCM_ADC_STEREO ;
      if( 1 == ul16Bit )
          ucFormatBits |= ES1371_PCM_ADC_16BIT ;
 
      HwRegRMW( ES1371_bSERFMT_OFF, 
                ES1371_PCM_ADC_STEREO|ES1371_PCM_ADC_16BIT,
                ucFormatBits ); 
      break;
  }
  return ;  
}

//--------------------------------------------------------------------------
//
//  Name: SetDMAChannelBuffer
//
//  Description: Set the buffer sizes of a particular DMA channel.
//
//  Parameters: UCHAR ucDMAChannel    : Index of the DMA channel to init
//              ULONG ulBufferLength  : Size in bytes of the whole DMA buffer
//              ULONG ulSamplesPerInt : Count of samples before interrupting
//
//  Returns: none   
//
//  Note:
//
//--------------------------------------------------------------------------
void
CES1371::SetDMAChannelBuffer( UCHAR ucDMAChannel,
                              ULONG ulBufferLength,
                              ULONG ulSamplesPerInt )
{
  ULONG ulDesiredBufferSize =  m_dmachannel[ucDMAChannel].ulDMABufSize;
  USHORT usInterruptCount = (USHORT) (ulSamplesPerInt - 1);

  m_dmachannel[ucDMAChannel].ulBufferLength  = ulBufferLength;
  m_dmachannel[ucDMAChannel].ulSamplesPerInt = ulSamplesPerInt;

  // buffer can't be bigger than half the physical buffer
  ulDesiredBufferSize = MIN( ulDesiredBufferSize, ulBufferLength ) ;

  switch ( ucDMAChannel )
  {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -