Exemplo n.º 1
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	[3933529]
IOReturn AppleTopazAudio::performSetPowerState ( UInt32 currentPowerState, UInt32 pendingPowerState )
{
	IOReturn			result = kIOReturnError;
	
	debugIOLog ( 6, "+ AppleTopazAudio::performSetPowerState ( %d, %d ) where pendingPowerState = %d", currentPowerState, pendingPowerState, pendingPowerState );
	switch ( pendingPowerState )
	{
		case kIOAudioDeviceSleep:
			if ( kIOAudioDeviceActive == mPluginCurrentPowerState )	//	[3954187]
			{
				result = performDeviceSleep ();
			}
			else
			{
				CODEC_Reset ();
				result = kIOReturnSuccess;
			}
			break;
		case kIOAudioDeviceIdle:
			if ( kIOAudioDeviceActive == mPluginCurrentPowerState )	//	[3954187]
			{
				result = performDeviceSleep ();
			}
			else
			{
				CODEC_Reset ();
				result = kIOReturnSuccess;
			}
			break;
		case kIOAudioDeviceActive:
			result = performDeviceWake ();
			break;
	}
	mPluginCurrentPowerState = pendingPowerState;
	debugIOLog ( 6, "- AppleTopazAudio::performSetPowerState ( %d, %d ) where pendingPowerState = %d, returns 0x%lX", currentPowerState, pendingPowerState, pendingPowerState, result );
	return result;
}
Exemplo n.º 2
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	Reset the device and flush the cached register set to the device.  This
//	is necessary for portable CPUs where power will have been removed from
//	the device during sleep.  After flushing the cached register values to
//	the device, place the device into the RUN state.
IOReturn AppleTopazAudio::performDeviceWake () {
	IOReturn		result = kIOReturnError;
	
	switch ( mCodecID ) {
		case kCodec_CS8406:		debugIOLog ( 5,  "+ AppleTopazAudio::performDeviceWake () using AppleTopazPluginCS8406" );		break;
		case kCodec_CS8416:		debugIOLog ( 5,  "+ AppleTopazAudio::performDeviceWake () using AppleTopazPluginCS8416" );		break;
		case kCodec_CS8420:		debugIOLog ( 5,  "+ AppleTopazAudio::performDeviceWake () using AppleTopazPluginCS8420" );		break;
		default:				debugIOLog ( 5,  "+ AppleTopazAudio::performDeviceWake () using AppleTopazPluginUNKNOWN" );		break;
	}

	CODEC_Reset ();
	if ( 0 != mTopazPlugin ) { 
		result = mTopazPlugin->performDeviceWake (); 
	}

	//	[3333215]	Codec operation may not be restored after wake from
	//	sleep so start state machine to recover codec operation.
	//	[3344893,3352595]	Recovery is only implemented if running on the internal 
	//	clock source since failure is associated with the sample rate converter 
	//	and the sample rate converter is not in use when running on the external 
	//	clock source.
	//	[4176829]	The CS8416 does not have a sample rate converter, so we should
	//	not employ the state machine for it.  If we do, the transition to
	//	kMachine2_setRxd_ILRCK, which calls useInternalCLK, and the transition to
	//	kMachine2_setRxd_AES3, which calls useExternalCLK, will cause two pops
	//	if things are un-muted.	
	if ( ( kTRANSPORT_MASTER_CLOCK == mClockSource ) && ( false == mDisableStateMachine2 ) ) {
		mCurrentMachine2State = kMachine2_startState;
	}
	else {
		mCurrentMachine2State = kMachine2_idleState;
	}
	
	mOptimizePollForUserClient_counter = kINITIAL_VALUE_FOR_POLL_FOR_USER_CLIENT_COUNT; //  [3686032]   initialize so log will show register dump a while longer

	switch ( mCodecID ) {
		case kCodec_CS8406:		debugIOLog ( 5,  "- AppleTopazAudio::performDeviceWake () using AppleTopazPluginCS8406 returns %lX", result );		break;
		case kCodec_CS8416:		debugIOLog ( 5,  "- AppleTopazAudio::performDeviceWake () using AppleTopazPluginCS8416 returns %lX", result );		break;
		case kCodec_CS8420:		debugIOLog ( 5,  "- AppleTopazAudio::performDeviceWake () using AppleTopazPluginCS8420 returns %lX", result );		break;
		default:				debugIOLog ( 5,  "- AppleTopazAudio::performDeviceWake () using AppleTopazPluginUNKNOWN returns %lX", result );		break;
	}
	return result;
}
Exemplo n.º 3
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	generalErrorRecovery:
//
//		Save away the current run state before stopping the S/PDIF codec.
//		Then reset the S/PDIF codec and restore all the register states.  
//		Complete the recovery by restoring the original S/PDIF codec run state.
//
void AppleTopazAudio::generalRecovery ( void ) {
	UInt8		data;
	
	FailIf ( 0 == mTopazPlugin, Exit );
	if ( !mGeneralRecoveryInProcess ) {
		mGeneralRecoveryInProcess = TRUE;
		data = mTopazPlugin->setStopMode ();
		CODEC_Reset();
		mTopazPlugin->flushControlRegisters ();
		mTopazPlugin->setRunMode ( data );
		
		if ( false == mDisableStateMachine2 ) {
			mCurrentMachine2State = kMachine2_startState;
		}
		else {
			mCurrentMachine2State = kMachine2_idleState;
		}
		
		mGeneralRecoveryInProcess = FALSE;
	}
Exit:
	return;
}
/*******************************************************************************
* Function Name  : CODEC_Config
* Description    : Configure the Codec in Headphone mode.
* Input          :  - OutputDevice: OutputDeviceHEADPHONE or OutputDeviceSPEAKER
*                :  - I2S_Standard: I2S communication standard could be I2S_Standard_Phillips
*                :       I2S_Standard_MSB or I2S_Standard_LSB.
*                :  - I2S_MCLKOutput: could be I2S_MCLKOutput_
*                :  - Volume:
* Output         : None
* Return         : 0-> correct communication, else wrong communication
*******************************************************************************/
uint32_t CODEC_Config(uint16_t OutputDevice, uint16_t I2S_Standard, uint16_t I2S_MCLKOutput, uint8_t Volume)
{
   uint32_t Standard = 0, counter = 0; 
 
  /* Configure the IO Expander (Codec Reset pin) */
  IOE_Config();
  
  /* Configure the Codec related IOs */
  CODEC_GPIO_Config();
  
  /* Reset the Codec Registers */
  CODEC_Reset();
  
  /* Determine the I2S standard used */
  switch (I2S_Standard)
  {
    case I2S_Standard_Phillips:
      Standard = 0x04;
      break;
    case I2S_Standard_MSB:
      Standard = 0x00;
      break;
    default :
      Standard = 0x08;
      break;
  }

  /* Initialization phase --------------------------------------*/
  /* Keep Codec powered OFF */
  counter += CODEC_WriteRegister(0x02, 0x01);  

  switch (OutputDevice)
  {
    case OutputDevice_SPEAKER:
      counter += CODEC_WriteRegister(0x04, 0xFA); // SPK always ON & HP always OFF
      break;
      
    case OutputDevice_HEADPHONE:
      counter += CODEC_WriteRegister(0x04, 0xAF); // SPK always OFF & HP always ON 
      break;
      
    case OutputDevice_BOTH:
      counter += CODEC_WriteRegister(0x04, 0xAA); // SPK always ON & HP always ON
      break;
      
    case OutputDevice_AUTO:
      counter += CODEC_WriteRegister(0x04, 0x05);// Detect the HP or the SPK automatically 
      break;      
  }
  
  /* Clock configuration: Auto detection */  
  counter += CODEC_WriteRegister(0x05, 0x81); //Auto speed detection
  
  /* Config the Slave Mode and the audio Standard */  
   counter += CODEC_WriteRegister(0x06, Standard);
      
  /* Set the Master volume */
  CODEC_ControlVolume(Volume); 
  
  /* Power on the Codec */
  counter += CODEC_WriteRegister(0x02, 0x9E);

  /* Return the counter value */
  return counter;
}
Exemplo n.º 5
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool AppleTopazAudio::preDMAEngineInit (UInt32 autoClockSelectionIsBeingUsed) {
	UInt8			data;
	bool			result = false;
	
	debugIOLog (3,  "+ AppleTopazAudio::preDMAEngineInit ()" );

	FailIf ( NULL == mPlatformInterface, Exit );
	FailIf ( NULL == mAudioDeviceProvider, Exit );									//  [3648867]
	
	//  [3648867]   Ask the Provider for the transport interface index.  There
	//  is a hard association or binding between the transport interface index
	//  and the CS84xx device address as follows:
	//
	//  AD2		AD1		AD0		I2C Address		Transport Index
	//
	//   0		 0		 0		0x20			0
	//   0		 0		 1		0x22			1
	//   0		 1		 0		0x24			2
	//   0		 1		 1		0x26			3
	//   1		 0		 0		0x28			4
	//   1		 0		 1		0x2A			5
	//   1		 1		 0		0x2C			6
	//   1		 1		 1		0x2E			7
	//
	//  Since the transport index shifted by one is equal to the offset from the
	//  I2C base address, the target address can be easily calculated as follows:
	
	mOptimizePollForUserClient_counter = kINITIAL_VALUE_FOR_POLL_FOR_USER_CLIENT_COUNT;

	if ( autoClockSelectionIsBeingUsed ) {
		mDisableStateMachine2 = true;
	}
	else {
		mDisableStateMachine2 = false;
	}
	
	CODEC_Reset ();
	data = CODEC_ReadID();
	FailIf ( 0 == data, Exit );
	
	data &= kCS84XX_ID_MASK;
	data >>= baID;
	
	switch ( data )
	{
		case cs8406_id:			mCodecID = kCodec_CS8406;			break;
		case cs8416_id:			mCodecID = kCodec_CS8416;			break;
		case cs8420_id:			mCodecID = kCodec_CS8420;			break;
		default:				FailIf ( true, Exit );				break;
	}
	
	switch ( data )
	{
		case cs8406_id:			mTopazPlugin = AppleTopazPluginFactory::createTopazPlugin ( kCS8406_CODEC );			break;
		case cs8416_id:			mTopazPlugin = AppleTopazPluginFactory::createTopazPlugin ( kCS8416_CODEC );			break;
		case cs8420_id:			mTopazPlugin = AppleTopazPluginFactory::createTopazPlugin ( kCS8420_CODEC );			break;
		default:				FailIf ( true, Exit );				break;
	}
	FailIf (NULL == mTopazPlugin, Exit);
	
	mTopazPlugin->initPlugin ( mPlatformInterface, mAudioDeviceProvider, mCodecID );   //  [3648867]
	
	mTopazPlugin->initCodecRegisterCache ();
	result = mTopazPlugin->preDMAEngineInit ( autoClockSelectionIsBeingUsed );
	
Exit:
	debugIOLog (3,  "- AppleTopazAudio::preDMAEngineInit () returns %d", result );

	return result;
}
Exemplo n.º 6
0
/**
  * @brief  Configures the audio peripherals.
  * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
  *                       OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
  * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
  * @param  AudioFreq: Audio frequency used to play the audio stream.
  * @note   This function configure also that the I2S PLL input clock.    
  * @retval 0 if correct communication, else wrong communication
  */
uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
{ 
  uint8_t ret = AUDIO_ERROR;
  uint32_t deviceid = 0x00;
  RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
  uint8_t index = 0, freqindex = 0xFF;
  
  for(index = 0; index < 8; index++)
  {
    if(I2SFreq[index] == AudioFreq)
    {
      freqindex = index;
    }
  }
  HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 
  if(freqindex != 0xFF)
  {
    /* I2S clock config 
    PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) × (PLLI2SN/PLLM)
    I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
    RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
    RCC_ExCLKInitStruct.PLLI2S.PLLI2SN = I2SPLLN[freqindex];
    RCC_ExCLKInitStruct.PLLI2S.PLLI2SR = I2SPLLR[freqindex];
    HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);     
  } 
  else /* Default PLL I2S configuration */
  {
    /* I2S clock config 
    PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) × (PLLI2SN/PLLM)
    I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
    RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
    RCC_ExCLKInitStruct.PLLI2S.PLLI2SN = 258;
    RCC_ExCLKInitStruct.PLLI2S.PLLI2SR = 3;
    HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 
  }
  
  /* Reset the Codec Registers */
  CODEC_Reset();
  
  deviceid = cs43l22_drv.ReadID(AUDIO_I2C_ADDRESS);
  
  if((deviceid & CS43L22_ID_MASK) == CS43L22_ID)
  {  
    /* Initialize the audio driver structure */
    audio_drv = &cs43l22_drv; 
    ret = AUDIO_OK;
  }
  else
  {
    ret = AUDIO_ERROR;
  }
  
  if(ret == AUDIO_OK)
  {
    audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
    /* I2S data transfer preparation:
    Prepare the Media to be used for the audio transfer from memory to I2S peripheral */
    /* Configure the I2S peripheral */
    I2Sx_Init(AudioFreq);
  }
  
  return ret;
}