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

📄 hwctxt.cpp

📁 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
{
	DWORD         threadID; 

    	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_AC97Irq, sizeof(UINT32), &g_AC97SysIntr, sizeof(UINT32), NULL))
    	{
       	 RETAILMSG(1, (TEXT("ERROR: AC97Irq: Failed to request sysintr value for AC97 interrupt.\r\n")));
        }
	
	if (AC97_InterruptEvent == NULL)
	{
	    AC97_InterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
	    
	    if (NULL == AC97_InterruptEvent) {
			RETAILMSG(1,(TEXT("AC97 interrupt event Error1\r\n")));
	    }
    	
	    // initialize the card insertion interrupt event
	    if (!InterruptInitialize (g_AC97SysIntr, AC97_InterruptEvent, 0, 0)) {
			RETAILMSG(1,(TEXT("AC97 interrupt event Error2\r\n")));
	    }
	}

	if (AC97_Thread == NULL)
	{
		AC97_Thread = CreateThread(NULL,
		                             0,
		                             (LPTHREAD_START_ROUTINE)AC97InterruptThread,
		                             0,
		                             0,
		                             &threadID);
		
		if (NULL == AC97_Thread ) {
			RETAILMSG(1,(TEXT("Create AC97 Interrupt Thread Fail\r\n")));
		}	
	}
	RETAILMSG(1,(TEXT("Use AC97 Int for initialization\r\n")));
}

#endif

// Kingfish2 AC97 Initialize function
BOOL HardwareContext::AC97_Init()
{
	RETAILMSG(AC97_DEBUG,(_T("WAVDEV_AC97::AC97_Init()++\r\n")));
	
	//----- 1. IMPORTANT: By default, the internal clock is disabled.  To configure the controller ------
	//					  we must first enable it.
	// v_pCLKPWRreg->CLKCON |= AC97_INTERNAL_CLOCK_ENABLE;		// Enable the CPU clock to the AC97 controller

	//AC97_GPIO_Init();

	// v_pAC97regs->AC_GLBCTRL = 0;
	// Delay(10); //Sleep(5);
		
	// Write into the AC97 Global Control Register
	
	//Cold Reset 
	v_pAC97regs->AC_GLBCTRL = 0x1; 
	Delay(10); //Sleep(5);
	v_pAC97regs->AC_GLBCTRL = 0x0;
	Delay(10); //Sleep(5);

	//Ajay
	v_pAC97regs->AC_GLBCTRL = 0x1; 
	Delay(10); //Sleep(5);
	v_pAC97regs->AC_GLBCTRL = 0x0;
	Delay(10); //Sleep(5);

	//AC-link On
	v_pAC97regs->AC_GLBCTRL = (1<<2);
	Delay(10); //Sleep(5);

	//Transfer data enable using AC-link
	v_pAC97regs->AC_GLBCTRL = v_pAC97regs->AC_GLBCTRL | (1<<3);
	Delay(10); //Sleep(5);


	// Disable the Codec ready Interrupt Ajay
	v_pAC97regs->AC_GLBCTRL = v_pAC97regs->AC_GLBCTRL | (1<<22);
	Delay(10); //Sleep(5);

	//while (!(v_pAC97regs->AC_GLBSTAT& 0x400000));

	RETAILMSG(AC97_DEBUG,(_T("WAVEDEV_AC97::AC97 Codec Ready!\r\n")));	
	
	v_pAC97regs->AC_GLBCTRL &= ~(0x400000);	// codec ready interrupt disable

	Delay(10); //Sleep(5);

#if AC97_RECORD_MICIN
   v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3f<<8)) | 0x2200; // PCM_OUT=DMA,PCM_IN=OFF,MIC=DMA;
#else
   v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3f<<10)) | 0x2800; // PCM_OUT=DMA,PCM_IN=DMA,MIC=OFF;
#endif
	RETAILMSG(AC97_DEBUG,(_T("WAVDEV_AC97::AC97_Init()--\r\n")));

	return TRUE;
}

BOOL HardwareContext::Codec_channel()
{

	// Kingfish2 AC97
	if( m_InputDMARunning & m_OutputDMARunning )
	{
		RETAILMSG(AC97_DEBUG1,(_T("Codec_channel() - In & Out\r\n")));
		WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_D0);		// ADC, DAC power up
	}	   
	else if( m_InputDMARunning )
	{
		RETAILMSG(AC97_DEBUG1,(_T("Codec_channel() - In\r\n")));
	    	WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR1);		// DAC power down
	   	//WriteCodecRegister(AC97_POWER_DOWN1, 0xb9cf);
          	//WriteCodecRegister(AC97_POWER_DOWN2, 0xbff0); 
		
	}
	else if( m_OutputDMARunning )
	{
		RETAILMSG(AC97_DEBUG1,(_T("Codec_channel() - Out\r\n")));
		WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR0);		// ADC power down	
	}
	else
	{
		RETAILMSG(AC97_DEBUG1,(_T("Codec_channel() - none\r\n")));
	  	WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR1|AC97_PWR_PR0);		// ADC/DAC power down
	}

    return(TRUE);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		InitCodec()

Description:	Initializes the audio codec chip.

Notes:			The audio codec chip is intialized for output mode
				but powered down.  To conserve battery life, the chip
				is only powered up when the user starts playing a 
				file.

				Specifically, the powerup/powerdown logic is done 
				in the AudioMute() function.  If either of the 
				audio channels are unmuted, then the chip is powered
				up; otherwise the chip is powered own.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitCodec()
{
	USHORT CodecRead;                             
	ULONG CodecVendorID, CodecRevision;           

	RETAILMSG(AC97_DEBUG, (TEXT("+++InitCodec\r\n")));
 	                                             
	// write the Codec software reset
	// 00h
	WriteCodecRegister(AC97_RESET, 0x683F);   
	
	// Enable the VRA
	// 2Ah
	WriteCodecRegister(AC97_EXT_AUDIO_CONTROL, AC97_ENABLE_VRA);

	WriteCodecRegister(AC97_PCM_DAC_RATE, 44100); // Write default Sample rate for DAC
	WriteCodecRegister(AC97_PCM_ADC_RATE, 44100); // Write default Sample rate for DAC
  
	// get the Vendor ID and revision 
	// 7Ch            
	CodecVendorID = ULONG(ReadCodecRegister( AC97_VENDOR_ID1 )) << 16;
	
	// 7E
	CodecRead = ReadCodecRegister( AC97_VENDOR_ID2 );
	
	CodecVendorID |= ULONG(CodecRead) & 0x0000ff00;
	CodecRevision = ULONG(CodecRead) & 0x000000ff;

	if ( !( CodecVendorID == AC97_VENDOR_SIGMATEL && CodecRevision == 0x66)) 
	{
		// now power down the Analog section of the AC97
		// and power it back up.  This forces the Sigmatel
		// to calibrate it's analog levels
		// 26h 
		WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_ANLOFF );
		Delay(10); //Sleep(5);
		RETAILMSG(AC97_DEBUG,(_T("WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_ANLOFF)\r\n")));
	}

	// Turn Power on for sections
	// 26h
	WriteCodecRegister( AC97_POWER_CONTROL, AC97_PWR_D0 );
	
	// Write the Analog reg
	// 6Eh
	//WriteCodecRegister( AC97_ANALOG_SPEC, 0x0000 );
	
	// write HP Out Value
	// 04h
	WriteCodecRegister( AC97_HEADPHONE_VOL, 0x0404 ); //0x0202); //0x0404 );
		
	// Mute unusing analog source except -------------------------------	
	// PCBEEP_VOL - 0ah
	WriteCodecRegister( AC97_PCBEEP_VOL, 0x8000 );
	// PHONE_VOL - 0ch
	WriteCodecRegister( AC97_PHONE_VOL, 0x8000 );
	// LINEIN_VOL - 10h
	WriteCodecRegister( AC97_LINEIN_VOL, 0x8000 );
	// CD_VOL - 12h
	WriteCodecRegister( AC97_CD_VOL, 0x8000 );
	// VIDEO_VOL - 14h
	WriteCodecRegister( AC97_VIDEO_VOL, 0x8000 );
	// AUX_VOL - 16h
	WriteCodecRegister( AC97_AUX_VOL, 0x8000 );
	
	// write the wave out volume
	// 18h
	WriteCodecRegister( AC97_PCMOUT_VOL, 0x0505 ); //0x0000 ); //0x0606 );
	
	// Init MIC-IN configurations
	// 20h
	WriteCodecRegister( AC97_GENERAL_PURPOSE, 0x0000 );	//MIC1 Selected


    	
#if AC97_RECORD_MICIN

    // ADC Gain Control, 30dB
	// BOOSTEN =1
    // tmp = ReadCodecRegister(AC97_MIC_VOL) & ~(0x1<<6);
    // WriteCodecRegister(AC97_MIC_VOL, tmp | (0x1<<6));
    WriteCodecRegister( AC97_MIC_VOL, (1<<15)|(1<<6) ); // Mute & BOOTEN
    
	//ADC Input Slot => left slot6, right slot9, MIC GAIN VAL=1
	WriteCodecRegister( AC97_INTR_PAGE, 0x0 );
	
	WriteCodecRegister( AC97_ANALOG_SPEC, 0x0020 );
	
	//Left, Right => MIC
	WriteCodecRegister( AC97_RECORD_SELECT, AC97_RECMUX_MIC );

	// set up a default record gain
	// 1Ch
	//WriteCodecRegister( AC97_RECORD_GAIN, AC97_RECORD_GAIN_VAL );
    WriteCodecRegister( AC97_RECORD_GAIN, 0x0909 );

#else	

    WriteCodecRegister( AC97_LINEIN_VOL, 0x8808 );  //For PCM In
    
	//ADC Input Slot => left slot3, right slot4, MIC GAIN VAL=1
	WriteCodecRegister( AC97_INTR_PAGE, 0x0 );

    //Select Slots for ADC Data on AC Link Left=3 , Right=4
	WriteCodecRegister( AC97_ANALOG_SPEC, 0x0000 );  //For PCM IN
	
	//Left, Right => LineIn
	WriteCodecRegister( AC97_RECORD_SELECT, AC97_RECMUX_LINE );// for PCM In

	// set up a default record gain
	// 1Ch
	WriteCodecRegister( AC97_RECORD_GAIN, 0x0505 ); //For PCM In
	
#endif

	// Now write High Pass Filter Bypass Control Register
	// 78h
	WriteCodecRegister( AC97_HPF_BYPASS, AC97_HIPASS_DISABLE );
	RETAILMSG(AC97_DEBUG, (TEXT("---InitCodec\r\n")));
	
	return(TRUE);
}

MMRESULT HardwareContext::SetOutputGain (DWORD dwGain)
{
    m_dwOutputGain = dwGain & 0xffff; // save off so we can return this from GetGain - but only MONO
    // convert 16-bit gain to 5-bit attenuation
    UCHAR ucGain;
    if (m_dwOutputGain == 0) {
        ucGain = 0x3F; // mute: set maximum attenuation
    }
    else {
        ucGain = (UCHAR) ((0xffff - m_dwOutputGain) >> 11); // codec supports 64dB attenuation, we'll only use 32
    }
    ASSERT((ucGain & 0xC0) == 0); // bits 6,7 clear indicate DATA0 in Volume mode.

	// Kingfish2. I can't find output gain of CODEC
//	WriteCodecRegister( AC97_RECORD_GAIN, AC97_RECORD_GAIN_VAL );

    return MMSYSERR_NOERROR;
}

MMRESULT HardwareContext::SetOutputMute (BOOL fMute)
{
    m_fOutputMute = fMute;
	
	WriteCodecRegister(0x02, 0x8000); // OUT2 volume Muted. Kingfish2

    return MMSYSERR_NOERROR;
}

BOOL HardwareContext::GetOutputMute (void)
{
    return m_fOutputMute;
}

DWORD HardwareContext::GetOutputGain (void)
{
    return m_dwOutputGain;
}

BOOL HardwareContext::GetInputMute (void)
{
    return m_fInputMute;
}

MMRESULT HardwareContext::SetInputMute (BOOL fMute)
{
    m_fInputMute = fMute;
    return m_InputDeviceContext.SetGain(fMute ? 0: m_dwInputGain);
}

DWORD HardwareContext::GetInputGain (void)
{
    return m_dwInputGain;
}

MMRESULT HardwareContext::SetInputGain (DWORD dwGain)
{
    m_dwInputGain = dwGain;
    if (! m_fInputMute) {
        m_InputDeviceContext.SetGain(dwGain);
    }
    return MMSYSERR_NOERROR;
}




/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		InitOutputDMA()

Description:	Initializes the DMA channel for output.

Notes:			DMA Channel 2 is used for transmitting output sound
				data from system memory to the AC97 controller.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitOutputDMA()
{
	RETAILMSG(AC97_DEBUG,(_T("+++InitOutputDMA\r\n")));	
	//----- 1. Initialize the DMA channel for output mode and use the first output DMA buffer -----
    if (!g_PhysDMABufferAddr.LowPart)
    {
        DEBUGMSG(TRUE, (TEXT("ERROR:HardwareContext::InitOutputDMA: Invalid DMA buffer physical address.\r\n")));
        return(FALSE);
    }
    v_pDMAregs->DISRC1	= (int)(g_PhysDMABufferAddr.LowPart); 
    v_pDMAregs->DISRCC1 &= ~(SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);				// Source is system bus, increment addr

    //----- 2. Initialize the DMA channel to send data over the AC97 -----
    v_pDMAregs->DIDST1	= (int)(AC_PCMDATA_PHYS); 
    v_pDMAregs->DIDSTC1 |= (DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);	// Dest is  periperal bus, fixed addr

	//----- 3. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
	//		   single tx, single service, AC97 request, no auto-reload, half-word, tx count
	v_pDMAregs->DCON1	= (  HANDSHAKE_MODE | GENERATE_INTERRUPT | AC97PCMOUT_DMA1 | DMA_TRIGGERED_BY_HARDWARE 
#if	DMA_FLAG	// Kingfish2 AC97
//					| TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2 ) );				
					| TRANSFER_WORD | (AUDIO_DMA_PAGE_SIZE / 4 ) );
#else						   									
//					| NO_DMA_AUTO_RELOAD | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );	
					| NO_DMA_AUTO_RELOAD | TRANSFER_WORD | (AUDIO_DMA_PAGE_SIZE / 4 ) );
#endif						   

	
	//----- 4. Reset the playback pointers -----
	AUDIO_RESET_PLAYBACK_POINTER();
	
	DEBUGMSG(ZONE_FUNCTION,(TEXT("---InitOutputDMA\n")));
        RETAILMSG(AC97_DEBUG,(_T("---InitOutputDMA\r\n")));
	return TRUE;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		StartOutputDMA()

Description:	Starts outputting the sound data to the audio codec
				chip via DMA.

Notes:			Currently, both playback and record share the same
				DMA channel.  Consequently, we can only start this
				operation if the input channel isn't using DMA.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::StartOutputDMA()
{
	RETAILMSG(AC97_DEBUG,(_T("+++StartOutputDMA\r\n")));	
	
	if(!m_OutputDMARunning && (m_Dx == D0) )
    {
        //----- 1. Initialize our buffer counters -----
        m_OutputDMARunning=TRUE;
        m_OutBytes[OUT_BUFFER_A]=m_OutBytes[OUT_BUFFER_B]=0;

        //----- 2. Prime the output buffer with sound data -----
		m_OutputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;	
		ULONG OutputTransferred = TransferOutputBuffers(m_OutputDMAStatus);

      	//RETAILMSG(AC97_DEBUG,(_T("StartOutputDMA:OutputTransferred =>0x%x\n"), OutputTransferred));        
		//----- 3. If we did transfer any data to the DMA buffers, go ahead and enable DMA -----
		if(OutputTransferred)
        {
			//----- 4. Configure the DMA channel for playback -----
			if(!InitOutputDMA())
			{
				DEBUGMSG(ZONE_ERROR, (TEXT("HardwareContext::StartOutputDMA() - Unable to initialize output DMA channel!\r\n")));
				goto START_ERROR;
			}
			// Kingfish2. AC97
#if	DMA_FLAG
			v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x2<<12);	// 0x2 = DMA
#else
			v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x1<<12);	// 0x1 = PIO
#endif	

			//----- 5. Make sure the audio isn't muted -----
			AudioMute(DMA_CH_OUT, FALSE);					
			RETAILMSG(AC97_DEBUG,(_T("Start DMA Controller\r\n")));	
			//----- 6. Start the DMA controller -----
			AUDIO_RESET_PLAYBACK_POINTER();
			SELECT_AUDIO_DMA_OUTPUT_BUFFER_A();
			Codec_channel();								// Turn ON output channel
			// charlie, start A buffer
			AUDIO_OUT_DMA_ENABLE();
#if DMA_FLAG			
	        // wait for DMA to start.
	        delay_count = 0;

	        while((v_pDMAregs->DSTAT1&0xfffff)==0){
#if WAIT_DMA_END
				Sleep(1);
#else
   				if( delay_count++ > DELAY_COUNT )	break;
#endif
	        }        
	        // change the buffer pointer
	        SELECT_AUDIO_DMA_OUTPUT_BUFFER_B();
	        // Set DMA for B Buffer
#endif
        }
        else    // We didn't transfer any data, so DMA wasn't enabled
        {
            m_OutputDMARunning=FALSE;
        }
    }
    
    RETAILMSG(AC97_DEBUG,(_T("---StartOutputDMA\r\n")));	

	return TRUE;

START_ERROR:
	return FALSE;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		StopOutputDMA()

Description:	Stops any DMA activity on the output channel.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::StopOutputDMA()
{
	RETAILMSG(AC97_DEBUG,(_T("StopOutputDMA:%d\r\n"),m_OutputDMARunning));	
	//----- 1. If the output DMA is running, stop it -----
    if (m_OutputDMARunning)
	{
		m_OutputDMAStatus = DMA_CLEAR;				
		AUDIO_OUT_DMA_DISABLE();
		AUDIO_OUT_CLEAR_INTERRUPTS();
		// Kingfish2 AC97
		v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x0<<12);	// 0x0 = OFF
		AudioMute(DMA_CH_OUT, TRUE);	
	   }
	

⌨️ 快捷键说明

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