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

📄 codec.c

📁 windows ce 下ARM9音频驱动代码
💻 C
📖 第 1 页 / 共 2 页
字号:

    ErrNum              = AC97_PCM_OUT_VOLUME;                       
    if (!AAC_WriteCODECIndexRegister (AacRegPtr, AC97_PCM_OUT_VOLUME, 0x0808)) {;
        goto ErrorReturn;
    }

//******************************************************************************
//* If no errors were found, exit gracefully.
//* Else, we've jumped to ErrorReturn:
//*  Post a message and exit with a failure code.
//*
//******************************************************************************
    DEBUGMSG(1, (TEXT("CodecInitializeRegisters: Success\r\n")));
    return TRUE;

ErrorReturn:

    DEBUGMSG(1, (TEXT("CodecInitializeRegisters: failed (0x%x)\r\n"), ErrNum));
    return FALSE;
}


////////////////////////////////////////////////////////////////////////////////
//
// Name: CodecInitialize
//
// Description:
//   Initializes the codec.
//
// Parameters:
//   None described
//
// Return Value:
//   TRUE           - Successful initialization.
//
////////////////////////////////////////////////////////////////////////////////
BOOLEAN CodecInitialize(IN OUT PWAVE_DEVICE_INSTANCE WaveInstance)
{
    BOOLEAN         RoutineSuccess  = FALSE;
    BOOLEAN         Success;
    PCODEC_DEVICE   NewDevice;

    NewDevice   = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(*NewDevice));

    if(NewDevice == NULL)
    {
        DEBUGMSG(1, (TEXT("CodecInitialize: Failed to allocate codec structure\r\n")));
        goto ErrorReturn;
    }

    NewDevice->AacRegPtr        = WaveInstance->AacRegPtr;
    Success                     = CodecInitializeRegisters(NewDevice);

    if(Success == FALSE)
    {
        DEBUGMSG(1, ( TEXT("CodecInitialize: Failed to initialize registers\r\n")));
        goto ErrorReturn;
    }

    DEBUGMSG(1, (TEXT("CodecInitialize: Success\r\n")));
    RoutineSuccess              = TRUE;

ErrorReturn:
    WaveInstance->CodecDevice   = NewDevice;

    if(RoutineSuccess == FALSE)
    {
        CodecDeinitialize(WaveInstance);
    }
    return RoutineSuccess;
}


////////////////////////////////////////////////////////////////////////////////
//
// Name: CodecGetVolume
//
// Description:
//   Return the current volume setting.
//
// Parameters:
//   None described
//
// Return Value:
//   ULONG          - Current volume setting.
//
////////////////////////////////////////////////////////////////////////////////
ULONG CodecGetVolume(IN PCODEC_DEVICE CodecDevice)
{
    return CodecDevice->Volume;
}


////////////////////////////////////////////////////////////////////////////////
//
// Name: CodecSetVolume
//
// Description:
//   Set a new volume setting.
//
// Parameters:
//   Volume         - New volume level desired.
//
// Return Value:
//   TRUE           - Successful volume setting.
//
////////////////////////////////////////////////////////////////////////////////
BOOLEAN CodecSetVolume(IN OUT PCODEC_DEVICE CodecDevice, IN ULONG Volume)
{

    APB_AAC_REGS*   AacRegPtr;
    ULONG          Attenuation1;
    ULONG          Attenuation2;
    ULONG			tmp;
//	int loop;
//******************************************************************************
//* Volume comes in from CE as one of 6 levels:
//*   0xFFFFFFFF - Max volume
//*   0xCCCCCCCC
//*   0x99999999
//*   0x66666666
//*   0x33333333
//*   0x00000000 - Min volume
//*
//******************************************************************************

    AacRegPtr           = CodecDevice->AacRegPtr;
    CodecDevice->Volume = Volume;
    Attenuation1        = (ULONG) ((MAX_VOLUME - (Volume & 0xFFFF)) & 0xF);
    Attenuation2        = Attenuation1;

    if(Attenuation2 >= 8)
    {
        Attenuation1   |= 0x10;
	}   

    tmp                 = (Attenuation1 << 8) | Attenuation1;


    DEBUGMSG(1, (TEXT("CodecSetVolume: Volume=0x%X Attenuation=0x%X (0x%X)\r\n"), Volume, tmp, Attenuation1));

    AAC_WriteCODECIndexRegister(AacRegPtr, AC97_MASTER_VOLUME, tmp);


//*TSAT* 02-Jan-2003
// Cirrus CS4201 Data Sheet (CS4201_AudioCodec.pdf), Pg. 23.
//  - Analog Mixer Output Volume Registers (Index 02h - 04h)
//  - "If the HPCFG pin is tied 'low', register 02h controls the Headphone Volume and register 04h is a read-only register and
//     always returns 0000h when 'read'."
//  - On Aruba, HPCFG is tied to ground.
//  AAC_WriteCODECIndexRegister (AacRegPtr, AC97_ALT_LINE_LEVEL_OUT_VOLUME, tmp);

    return TRUE;
}




//******************************************************************************
//* POWER MANAGEMENT ROUTINES BELOW HERE.
//* THESE ROUTINES HAVE NOT BEEN ADAPTED FOR THE ARUBA PLATFORM.  02-Jan-2003
//*
//******************************************************************************
////////////////////////////////////////////////////////////////////////////////
//
// Name: Delay
//
// Description:
//   Delay during STANDBY.
//
// Parameters:
//   None
//
// Return Value:
//   None
//
////////////////////////////////////////////////////////////////////////////////
void Delay()
{
  PHYSICAL_ADDRESS  PhysAddr;
  ULONG             TmpVal;
  ULONG             StartVal;

//******************************************************************************
//* This delay routine is used when the system is in STANDBY mode and all
//*  the timer clocks are stopped at this point except the 1s RTC.
//* But the 1s resolution is too long for the delay and it will affect the
//*  performance when the system goes from RUN to STANDBY and reverse. So 
//*  we have to implement the software loop for the delay. As result, the 
//*  constant value used here may need to adjust if the CPU speed changes.
//*
//******************************************************************************
  if(RTCRegPtr == NULL) {
    PhysAddr.QuadPart   = APB_RTC_REGS_BASE;
    RTCRegPtr           = MmMapIoSpace(PhysAddr, sizeof(APB_RTC_REGS), FALSE);

    if(RTCRegPtr == NULL) {
        DEBUGMSG(1, (TEXT("CODEC.C:Delay: Unable to map RTC registers\r\n")));
        return;
    }
  }

#if 1
//******************************************************************************
//* Do dummy read for the delay loop
//*
//******************************************************************************
  for (TmpVal = 0; TmpVal < DELAY_VAL; TmpVal++) {
        StartVal        = READ_REGISTER_ULONG(&RTCRegPtr->RTCDR);
        StartVal++;
        StartVal        = READ_REGISTER_ULONG(&RTCRegPtr->RTCDR);
  }
#else
//******************************************************************************
//* Use the RTC
//*
//******************************************************************************
  StartVal              = READ_REGISTER_ULONG(&RTCRegPtr->RTCDR);
  TmpVal                = StartVal;
  StartVal             += 1;
  while(TmpVal <= StartVal) {
        TmpVal          = READ_REGISTER_ULONG(&RTCRegPtr->RTCDR);
  }
#endif
}


////////////////////////////////////////////////////////////////////////////////
//
// Name: AAC_Slot1Wait_Pmgt
//       AAC_Slot2Wait_Pmgt
//
// Description:
//   Wait for indicator bit to be set in AAC status register.
//
// Parameters:
//   aacRegPtr  - Pointer to AAC controller within the SOC.
//
// Return Value:
//   TRUE       - Success if bit was set by the AAC controller 
//
////////////////////////////////////////////////////////////////////////////////
//      Function to wait for the transmit on Slot 1
//      to happen correctly.
//      This prevents us from overwriting data while
//      waiting to transmit
BOOLEAN AAC_Slot1Wait_Pmgt (APB_AAC_REGS* aacRegPtr)
{
  int timeoutcounter;
  volatile ULONG * pAACRGIS = &(aacRegPtr->AACRGIS);

  Delay(); // Slowdown this routine because of HW bugs
  
  timeoutcounter = 100;
  while (!((*pAACRGIS) & AAC_RGIS_SLOT1TXCOMPLETE))
  {
        timeoutcounter--;
        if (timeoutcounter == 0)
        {
                return FALSE;
        }
  }

  return TRUE;
}


//      Function to wait for the data requested from
//      the AC97 to get into Slot 2
BOOLEAN AAC_Slot2Wait_Pmgt (APB_AAC_REGS* aacRegPtr)
{
  int timeoutcounter;
  volatile ULONG * pAACRGIS = &(aacRegPtr->AACRGIS);

  Delay(); // Slowdown this routine because of HW bugs

  timeoutcounter = 100;
  while (!((*pAACRGIS) & AAC_RGIS_SLOT2RXVALID))
  {
        timeoutcounter--;
        if (timeoutcounter == 0)
        {
                return FALSE;
        }
  }

  return TRUE;
}

////////////////////////////////////////////////////////////////////////////////
//
// Name: AC97Write_Pmgt
//
// Description:
//   Write data through the AAC controller to the codec.
//
// Parameters:
//   aacRegPtr  - Pointer to AAC controller within the SOC.
//   AC97Reg    - Index of codec register being written.
//   AC97Data   - Data to be loaded into the codec register.
//
// Return Value:
//   TRUE       - Success if register was written correctly.
//
////////////////////////////////////////////////////////////////////////////////
BOOLEAN AC97Write_Pmgt (APB_AAC_REGS* aacRegPtr, ULONG AC97Reg, ULONG AC97Data)
{
  ULONG JNK, JNK2;
  volatile ULONG * pAACS1DATA  = &(aacRegPtr->AACS1DATA);
  volatile ULONG * pAACS2DATA  = &(aacRegPtr->AACS2DATA);

  Delay(); // Slowdown this routine because of HW bugs
  DEBUGMSG(1,(TEXT("AC97Write - aacRegPtr=0x%x, AC97Reg=0x%x, AC97Data=0x%x\r\n"),
              (DWORD)aacRegPtr,AC97Reg,AC97Data));

  *pAACS2DATA = AC97Data;
  *pAACS1DATA = AC97Reg;

  if ((AAC_Slot1Wait_Pmgt(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 1st Slot1Wait\r\n")));
         return FALSE;
  }

  JNK = *pAACS2DATA;
  *pAACS1DATA = AC97Reg;
  if ((AAC_Slot1Wait_Pmgt(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 2nd Slot1Wait\r\n")));
         return FALSE;
  }
  if ((AAC_Slot2Wait_Pmgt(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 1st Slot2Wait\r\n")));
         return FALSE;
  }

  JNK = *pAACS2DATA;
  *pAACS1DATA = AC97Reg;
  if ((AAC_Slot1Wait_Pmgt(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 3rd Slot1Wait\r\n")));
         return FALSE;
  }
  if ((AAC_Slot2Wait_Pmgt(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 2nd Slot2Wait\r\n")));
         return FALSE;
  }

  JNK = *pAACS2DATA;
  JNK2 = *pAACS1DATA;
        
  if ((AC97Reg == 0) ||     // don't check data echo for reset cmd
      (JNK == AC97Data))    // for other cmd's echo should equal data sent
  {
    return TRUE;
  }
  else
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on data echo: 0x%x != 0x%x\r\n"),JNK,AC97Data));
         return FALSE;
  }
}

////////////////////////////////////////////////////////////////////////////////
//
// Name: AAC_WriteCODECIndexRegister_Pmgt
//
// Description:
//   Pass-through routine.
//
// Parameters:
//   aacRegPtr  - Pointer to AAC controller within the SOC.
//   AC97Reg    - Index of codec register being written.
//   Value      - Data to be loaded into the codec register.
//
// Return Value:
//   TRUE       - Success if register was written correctly.
//
////////////////////////////////////////////////////////////////////////////////
// AAC_WriteCODECIndexRegister
BOOLEAN AAC_WriteCODECIndexRegister_Pmgt (APB_AAC_REGS* aacRegPtr, ULONG AC97Reg, ULONG Value)
{
    return AC97Write_Pmgt (aacRegPtr, AC97Reg, Value);
}



//******************************************************************************
//* ORIGINAL CODEC ROUTINES.
//* OBSOLETE AS OF 31-DEC-2002
//*
//******************************************************************************

//*TSAT* 31-Dec-2002
#ifdef THE_ORIGINAL_CODEC_AC97WRITE_ROUTINE
// AC97 Write
BOOLEAN AC97Write (APB_AAC_REGS* aacRegPtr, ULONG AC97Reg, ULONG AC97Data)
{
  ULONG JNK, JNK2;
  volatile ULONG * pAACS1DATA  = &(aacRegPtr->AACS1DATA);
  volatile ULONG * pAACS2DATA  = &(aacRegPtr->AACS2DATA);

  DEBUGMSG(1,(TEXT("AC97Write - aacRegPtr=0x%x, AC97Reg=0x%x, AC97Data=0x%x\r\n"),
              (DWORD)aacRegPtr,AC97Reg,AC97Data));

  *pAACS2DATA = AC97Data;
  *pAACS1DATA = AC97Reg;

  if ((AAC_Slot1Wait(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 1st Slot1Wait\r\n")));
     return FALSE;
  }

  JNK = *pAACS2DATA;
  *pAACS1DATA = AC97Reg;

  if ((AAC_Slot1Wait(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 2nd Slot1Wait\r\n")));
     return FALSE;
  }
  if ((AAC_Slot2Wait(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 1st Slot2Wait\r\n")));
     return FALSE;
  }

  JNK = *pAACS2DATA;
  *pAACS1DATA = AC97Reg;

  if ((AAC_Slot1Wait(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 3rd Slot1Wait\r\n")));
     return FALSE;
  }
  if ((AAC_Slot2Wait(aacRegPtr)) == FALSE)
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on 2nd Slot2Wait\r\n")));
     return FALSE;
  }

  JNK = *pAACS2DATA;
  JNK2 = *pAACS1DATA;
        
  if ((AC97Reg == 0) ||     // don't check data echo for reset cmd
      (JNK == AC97Data))    // for other cmd's echo should equal data sent
  {
    return TRUE;
  }
  else
  {
     DEBUGMSG(1,(TEXT("AC97Write, failure on data echo: 0x%x != 0x%x\r\n"),JNK,AC97Data));
     return FALSE;
  }
}
#endif //the_original_codec_ac97write_routine



//*TSAT* 31-Dec-2002
#ifdef THE_ORIGINAL_CODEC_AC97READ_ROUTINE
// AC97 Read
ULONG AC97Read (APB_AAC_REGS* aacRegPtr, ULONG AC97Reg)
{
  ULONG Data, JNK2;
  volatile ULONG * pAACS1DATA  = &(aacRegPtr->AACS1DATA);
  volatile ULONG * pAACS2DATA  = &(aacRegPtr->AACS2DATA);

  *pAACS2DATA = 0x5555;
  Data = *pAACS2DATA;
  *pAACS1DATA = AC97Reg;
  AAC_Slot1Wait(aacRegPtr);
  AAC_Slot2Wait(aacRegPtr);

  Data = *pAACS2DATA;
  *pAACS1DATA = AC97Reg;
  AAC_Slot1Wait(aacRegPtr);
  AAC_Slot2Wait(aacRegPtr);

  Data = *pAACS2DATA;
  JNK2 = *pAACS1DATA;

  return Data;
}
#endif //the_original_codec_ac97read_routine

⌨️ 快捷键说明

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