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

📄 ac97.c

📁 三星2443芯片
💻 C
📖 第 1 页 / 共 3 页
字号:
/*======================================================================

 Project Name : S3C2443

 Copyright 2006 by Samsung Electronics, Inc.
 All rights reserved.

 Project Description :
 This software is only for verifying functions of the S3C2443. 
 Anybody can use this code without our permission.

 File Name    : AC97.c
 Description  : S3C2443 AC97 module code
 Author       : Junon Jeon
 Dept         : AP
 Created Date : 2006.06.02
 Version      : 0.0
 History
   R0.0 (2006.06.02): Junon draft
		- This code is derived from S3C2460A AC97 test code.
   	    - This S3C2443 AC97 test code works with WM9710 AC97 CODEC on the SMDK2443. 
	    - AC97 PCM-In in DMA or interrupt mode is supported.
        - AC97 PCM-Out in DMA or interrupt mode is supported.
	    - Volume up/down is available, when codec plays PCM data.
        - AC97 power down mode test is supported.	
        - AC97 reset timing check is supported.
        - Variable ADC/DAC operation is supported. 
		
=======================================================================*/

#include "system.h"
#include "ac97.h"


#define AC97_REC_LEN 0xfffff*4	//Max value of DMA Transfer Counter (20bit) = 0xfffff, Date Size=Word (4bytes)
//#define AC97_REC_LEN 0xfffff

#define DOWN_BUF _NONCACHE_STARTADDRESS
#define PCM_OUT_TRIGGER 8
#define PCM_IN_TRIGGER 8
#define AC97_PCM_OUT_THRESHOLD (1<<18)
#define AC97_PCM_IN_THRESHOLD (1<<17)
#define AC97_MIC_IN_THRESHOLD (1<<16)

// Global variables
unsigned int save_AC97_rGPECON, save_AC97_rGPEDAT, save_AC97_rGPEUDP;
unsigned int AC97_size, AC97_fs;
unsigned int Output_Volume,Input_Volume;
unsigned int *Rec_AC97_BUF, *Play_AC97_BUF, *End_AC97_BUF;
volatile static int	timer_exit=0;

volatile short AC97_Out_INT_Exit = 0;
volatile short AC97_In_INT_Exit =0;

unsigned char *AC97_BUF,*AC97_temp;
unsigned char Volume_Control;

char AC97_Rec_Done = 0;
char Codec_Ready_Irq;
char AC97_mute = 1;
char Codec_Ready = 1;

// Functions
// GPIO port setting
void AC97_Port_Init(void);
void AC97_Port_Return(void);
// AC97 Controller configuration
void AC97_Controller_State(void);
void AC97_Init(void);
// AC97 CODEC control
unsigned short AC97_Codec_Cmd(unsigned char CMD_Read, unsigned char CMD_Offset, unsigned short CMD_Data);
void AC97_CodecInit_PCMOut(unsigned short AC97_fs);
void AC97_CodecInit_PCMIn(unsigned short AC97_fs);
void AC97_CodecInit_MICIn(unsigned short AC97_fs);
void AC97_CodecInit_PD(void);
void AC97_CodecExit_PCMOut(void);
void AC97_CodecExit_PCMIn(unsigned short DACs_off);
void AC97_CodecExit_MICIn(unsigned short DACs_off);
void PCM_In_Volume( unsigned char Up_Down_Volume);
void PCM_Out_Volume( unsigned char Up_Down_Volume);
void Download_PCM_File(void);
// AC97 data in/out function
void AC97_PCMout_DMA1(unsigned int PCM_Size);
void AC97_PCMout_INT(unsigned int PCM_Size);
void AC97_PCMin_DMA2(unsigned int PCM_Size);
void AC97_PCMin_INT(unsigned int PCM_Size);
void AC97_MICin_DMA3(unsigned int MIC_Size);
void AC97_MICin_INT(unsigned int PCM_Size);
static void __irq DMA1_Play_Done(void);
static void __irq DMA2_Rec_Done(void);
static void __irq DMA3_Rec_Done(void);
void __irq AC97_Codec_Ready(void);
void __irq Irq_AC97_PCMout(void);
void __irq Irq_AC97_PCMin(void);
void __irq Irq_AC97_MICin(void);
static void __irq IsrWatchdog(void);
void __irq RxInt(void);

// other library
unsigned short AC97_Select_SamplingRate(void);
float delay_func(unsigned short num_delay); 
 

void * func_ac97_test[][2]=
{	
	//AC97 Function Test Item
	(void *)Powerdown_Test_AC97,	"AC97 Power Down   ",  
	(void *)PCM_Out_Test_AC97,		"Play Wave file",   
	(void *)PCM_In_Out_Test_AC97,	"Record Sound via LineIn and Play it  ",   
	(void *)MICin_Test_AC97,		"Record Voice via MIC and Play it      ",    
	(void *)Reset_Test_AC97,		"AC97 Reset Timing Check ",
	0,0
};


void Test_AC97(void)
{
	int i;

	AC97_Port_Init();
	
	while(1)
	{
		i=0;
		printf("\n\n==================== AC97 Function Test ====================\n\n");
		while(1)
		{   //display menu
			printf("%2d:%s",i,func_ac97_test[i][1]);
			i++;
			if((int)(func_ac97_test[i][0])==0)
			{
				printf("\n");
				break;
			}
			if((i%2)==0)
			printf("\n");
		}
		printf("\n============================================================");
		printf("\nSelect #Item or Press enter key to exit:");
		i = GetIntNum();
			
		
		if(i==-1) break;		// return.	
		if(i>=0 && (i<(sizeof(func_ac97_test)/8)) )	// select and execute...
			( (void (*)(void)) (func_ac97_test[i][0]) )();
	}
	
	rAC_GLBCTRL = 0;
}


//============================== [ AC97 Drivers ] ===============================

void AC97_Port_Init(void)
{
	//Push AC97 GPIO port configuration
	save_AC97_rGPEDAT=rGPEDAT;
	save_AC97_rGPECON=rGPECON; 
	save_AC97_rGPEUDP=rGPEUDP;

	printf(" Which pads would you select for AC97? \n 1) muxed IIS pads	2) muxed SD pads\n");
	if (getchar()=='2')
	{
		//---------------------------------------------------------------------
		//PORT E GROUP
		//Ports  :  GPE4		GPE3		GPE2		GPE1		GPE0 
		//Signal :  AC97 SDO	AC97 SDI	AC97 BITCLK	AC97 SYNC	AC97 RESETn 
		//Binary :  11,			11,			11,			11,			11    
		//---------------------------------------------------------------------
		rGPECON |= (0x3ff<<10); // GPE[10:6]=> AC97 function muxed SD
		rGPEUDP |= (0x3ff<<10); // The pull up function is disabled GPE[10:6]
		
		rGPECON &= ~(0x3ff); // GPE[4:0]=> AC97 function muxed IIS
		rGPEUDP |= 0x1f; // The pull up function is disabled GPE[4:0]
	}
	else
	{
		//---------------------------------------------------------------------
		//PORT E GROUP
		//Ports  :  GPE4		GPE3		GPE2		GPE1		GPE0 
		//Signal :  AC97 SDO	AC97 SDI	AC97 BITCLK	AC97 SYNC	AC97 RESETn 
		//Binary :  11,			11,			11,			11,			11    
		//---------------------------------------------------------------------
		
		rGPECON &= ~(0x3ff<<10); // GPE[10:6]=> AC97 function muxed SD
		rGPEUDP |= (0x3ff<<10); // The pull up function is disabled GPE[10:6]
		
		rGPECON |= 0x3ff; // GPE[4:0]=> AC97 function muxed IIS
		rGPEUDP |= 0x1f; // The pull up function is disabled GPE[4:0]
	}    	
}


void AC97_Port_Return(void)
{
	//Pop AC97 GPIO port configuration
	rGPECON=save_AC97_rGPECON; 
	rGPEDAT=save_AC97_rGPEDAT;
	rGPEUDP=save_AC97_rGPEUDP;
}


void AC97_Controller_State(void)
{
	unsigned char state;
    
    	state=(unsigned char)(rAC_GLBSTAT);

     	switch(state)
    	{
		case 0:
		printf("AC97 Controller State: Idle\n"); 
		break;
	
		case 1:
			printf("AC97 Controller State: Init\n"); 
		break;

		case 2:
		       printf("AC97 Controller State: Ready\n"); 
		break;
		
		case 3:
			printf("AC97 Controller State: Active\n"); 
		break;

		case 4:
			printf("AC97 Controller State: LP\n"); 
		break;

		case 5:
			printf("AC97 Controller State: Warm\n"); 
		break;

		default:
		break;
     	}
}


void AC97_Init(void)
{
	int i=0;

	printf("\nAC97 Initialization...\n");	
	
 	//Cold Reset 
	rAC_GLBCTRL = 0x1;	// controller and codec cold reset
	Delay(1000);			// delay for controller safety reset
	rAC_GLBCTRL = 0x0;	// controller and codec normal mode
	Delay(1000);		
	rAC_GLBCTRL = 0x1;							
	Delay(1000);									
	rAC_GLBCTRL = 0x0;						
	Delay(1000);	
	
	//AC-link On
	rAC_GLBCTRL = (1<<2);
	Delay(1000);	
	AC97_Controller_State();

	//Transfer data enable using AC-link
	rAC_GLBCTRL |= (1<<3);	// AC97 Data transfer active 
	Delay(1000);	
	AC97_Controller_State();
	printf("\nAC97-Link On...\n");
       
	//Codec Ready Check using Codec Ready Interrupt
	Codec_Ready_Irq =0;	
	pISR_WDT_AC97 = (unsigned)AC97_Codec_Ready;	

	ClearPending(BIT_WDT_AC97);	
	rSUBSRCPND=(BIT_SUB_AC97);

   	rINTMSK=~(BIT_WDT_AC97);			
   	rINTSUBMSK=~(BIT_SUB_AC97);

   	rAC_GLBCTRL |= 0x400000;
   	
	while(!Codec_Ready_Irq)
	{

	 	printf(".");
         	Delay(3000);
         	i++;
         	
         	if(i==20)
		break;
	 }

	printf("\n");

	if(i==20)
	{
		printf("\nAC97 codec is not ready.");
		printf("\nCheck on connection between S3C2460 and AC97 CODEC.\n");
		printf("\nBye. ");
		Codec_Ready = 0;
	}
}


unsigned short AC97_Codec_Cmd(unsigned char CMD_Read, unsigned char CMD_Offset, unsigned short CMD_Data)
{ 
	 unsigned short Codec_Stat;

	if(CMD_Read == 0)
	{
		rAC_CODEC_CMD = (0<<23)|(CMD_Offset<<16)|(CMD_Data<<0);
		delay_func(2); //32 us delay 
		return 1;
	}
	else if (CMD_Read ==1) 
	{
		rAC_CODEC_CMD = (1<<23)|(CMD_Offset<<16)|(CMD_Data<<0);
		Delay(1000);

		Codec_Stat = (unsigned short)(rAC_CODEC_STAT & 0xFFFF);
		Delay(1000);
		return Codec_Stat;
	}
	else 
		return 0;
        
}


void AC97_CodecInit_PD(void)
{
	printf("\nAC97 Codec Soft Reset\n");
	AC97_Codec_Cmd(0,0x00,0x683F);		//Codec Soft Reset : 16bit In/Out  (stac9766/67) 	
	printf("AC97 Codec 0x26 Reg.: 0x%x\n\n", AC97_Codec_Cmd(1,0x26,0x0000));		
}


void AC97_CodecInit_PCMIn( unsigned short AC97_fs)
{
	
	AC97_Codec_Cmd(0,0x00,0x683F);		//codec soft reset 	

	AC97_Codec_Cmd(0,0x26,(1<<9));		//all power on except DAC Block
	printf("\nAC97 Codec 0x26 Reg.: 0x%x\n\n", AC97_Codec_Cmd(1,0x26,0x0000));
	
	AC97_Codec_Cmd(0,0x2A,0x0001);		//variable rate enable	
	printf("VRA Enable(1)/Disable(0): 0x%x\n",(0x1&AC97_Codec_Cmd(1,0x2A,0x0001)));
	
	if(AC97_fs==48000){
	//ADC Sampling frequency 48kHz
	AC97_Codec_Cmd(0,0x32,0xbb80);	
	}
	else if(AC97_fs==44100){
	//ADC Sampling frequency 44.1kHz
	AC97_Codec_Cmd(0,0x32,0xac44);
	}
	else if(AC97_fs==22050){
	//ADC Sampling frequency 22.05kHz
	AC97_Codec_Cmd(0,0x32,0x5622);	 	
	}
	else if(AC97_fs==8000){
	//ADC Sampling frequency 8kHz
	AC97_Codec_Cmd(0,0x32,0x1F40);	 	
	}

	AC97_Codec_Cmd(0,0x10,0x1010);		//line in volume on
	//* khs.050504
	//*	removed because seem that this is not necessary
	//AC97_Codec_Cmd(0,0x6e,0x0000);		//All Analog Mode, ADC Input select => left slot3, right slot4
	AC97_Codec_Cmd(0,0x1a,0x0505);		//record source select => Stereo Mix
	AC97_Codec_Cmd(0,0x1c,0x0909);		//record gain is initial
	//* khs.050504
	//*	removed because seem that this is not necessary
	//AC97_Codec_Cmd(0,0x78,0x0001);		//ADC HPF Bypass
	AC97_Codec_Cmd(0,0x20,0x0000);		//General Reg.
	
	Input_Volume = 	AC97_Codec_Cmd(1,0x10,0x0000);	      //Line In volume	
	printf("Current Line-In Volume level : 0x%04x\n",Input_Volume);	
}


void AC97_CodecInit_PCMOut( unsigned short AC97_fs)
{	
	AC97_Codec_Cmd(0,0x00,0x683F);		//codec soft reset	

	AC97_Codec_Cmd(0,0x2A,0x0001);		//variable rate enable	
	//printf("\nVRA Enable(1)/Disable(0): 0x%x\n", (0x1&AC97_Codec_Cmd(1,0x2A,0x0001)));
	
	if(AC97_fs==48000){
	//DAC Sampling frequency 48kHz
	AC97_Codec_Cmd(0,0x2C,0xbb80);
	}
	else if(AC97_fs==44100){
	//DAC Sampling frequency 44.1kHz
	AC97_Codec_Cmd(0,0x2C,0xac44);
	}
	else if(AC97_fs==22050){
	//DAC Sampling frequency 22.05kHz
	AC97_Codec_Cmd(0,0x2C,0x5622);		
	}
	else if(AC97_fs==8000){
	//DAC Sampling frequency 22.05kHz
	AC97_Codec_Cmd(0,0x2C,0x1F40);		
	}

	AC97_Codec_Cmd(0,0x26, (1<<8));		// all power on except ADC blcok
	printf("AC97 Codec 0x26 Reg.: 0x%x\n\n", AC97_Codec_Cmd(1,0x26,0x0000));

	AC97_Codec_Cmd(0,0x18,0x0000);		// PCM out volume on
	AC97_Codec_Cmd(0,0x20,0x0000);		// general purpose
	AC97_Codec_Cmd(0,0x04,0x1A1A);		// Aux out(HP out) volume on
	
	Output_Volume = AC97_Codec_Cmd(1,0x04,0x00000);	//HP out volume
	printf("Current Headphone Volume level : 0x%04x\n",Input_Volume);
}


void AC97_CodecInit_MICIn(unsigned short AC97_fs)
{
	AC97_Codec_Cmd(0,0x00,0x683F);		//codec soft reset 	
	
	AC97_Codec_Cmd(0,0x2A,0x0001);		//variable rate enable	
	printf("VRA Enable(1)/Disable(0): 0x%x\n",(0x1&AC97_Codec_Cmd(1,0x2A,0x0001)));
	
	if(AC97_fs==48000){
		//ADC Sampling frequency 48kHz
		AC97_Codec_Cmd(0,0x32,0xbb80);	
	}
	else if(AC97_fs==44100){
		//ADC Sampling frequency 44.1kHz
		AC97_Codec_Cmd(0,0x32,0xac44);
	}
	else if(AC97_fs==22050){
		//ADC Sampling frequency 22.05kHz
		AC97_Codec_Cmd(0,0x32,0x5622);	 
	}
	else if(AC97_fs==8000){
		//ADC Sampling frequency 8kHz
		AC97_Codec_Cmd(0,0x32,0x1F40);	 
	}
	
	AC97_Codec_Cmd(0,0x26,(1<<9));		//all power on except DAC Block
	printf("\nAC97 Codec 0x26 Reg.: 0x%x\n\n", AC97_Codec_Cmd(1,0x26,0x0000));
	
	AC97_Codec_Cmd(0,0x20,0x0000);		//MIC1 Selected
	AC97_Codec_Cmd(0,0x6e,0x0024);		//ADC Input Slot => left slot6, right slot9, MIC GAIN VAL =1 
	AC97_Codec_Cmd(0,0x0e,0x0040);		//BOOSTEN =1
	AC97_Codec_Cmd(0,0x1a,0x0000);		//Left, Right => MIC
	AC97_Codec_Cmd(0,0x1c,0xff);		
	AC97_Codec_Cmd(0,0x78,0x0001);		//ADC HPF Bypass
	
	Input_Volume = 	AC97_Codec_Cmd(1,0x1c,0x0000);	      //Record Volume	
}


void AC97_CodecExit_PCMOut(void)
{
	//DACs off
	printf("\n\n=>DACs off PR1\n");
	AC97_Codec_Cmd(0,0x26,(1<<8)|(1<<9));
	AC97_Controller_State();
	printf("AC97 Codec Powerdown Ctrl/Stat 0x26 Reg.: 0x%x\n", AC97_Codec_Cmd(1,0x26,0x0000));	

	//Analog off
	printf("\n=>Analog off PR2\n");
	AC97_Codec_Cmd(0,0x26,(1<<8)|(1<<9)|(1<<10));
	AC97_Controller_State();
	printf("AC97 Codec Powerdown Ctrl/Stat 0x26 Reg.: 0x%x\n", AC97_Codec_Cmd(1,0x26,0x0000));	

	//Digital I/F off
	printf("\n=>Digital I/F off PR4\n");
	AC97_Codec_Cmd(0,0x26,(1<<8)|(1<<9)|(1<<10)|(1<<12));
	AC97_Controller_State();
	printf("AC97 Codec Powerdown Ctrl/Stat 0x26 Reg.: 0x%x\n", AC97_Codec_Cmd(1,0x26,0x0000));	

}


void AC97_CodecExit_PCMIn(unsigned short DACs_off)
{
	//ADCs off
	printf("\n\n=>ADCs off PR0\n");
	AC97_Codec_Cmd(0,0x26,(1<<8));
	AC97_Controller_State();
	printf("AC97 Codec Powerdown Ctrl/Stat 0x26 Reg.: 0x%x\n", AC97_Codec_Cmd(1,0x26,0x0000));

	if(DACs_off == 1)
	{
		//DACs off
		printf("\n\n=>DACs off PR1\n");
		AC97_Codec_Cmd(0,0x26,(1<<8)|(1<<9));
		AC97_Controller_State();
		printf("AC97 Codec Powerdown Ctrl/Stat 0x26 Reg.: 0x%x\n", AC97_Codec_Cmd(1,0x26,0x0000));
	}
	//Analog off
	printf("\n=>Analog off PR2\n");
	AC97_Codec_Cmd(0,0x26,(1<<8)|(1<<9)|(1<<10));
	AC97_Controller_State();
	printf("AC97 Codec Powerdown Ctrl/Stat 0x26 Reg.: 0x%x\n", AC97_Codec_Cmd(1,0x26,0x0000));	

	//Digital I/F off
	printf("\n=>Digital I/F off PR4\n");
	AC97_Codec_Cmd(0,0x26,(1<<8)|(1<<9)|(1<<10)|(1<<12));
	AC97_Controller_State();
	printf("AC97 Codec Powerdown Ctrl/Stat 0x26 Reg.: 0x%x\n", AC97_Codec_Cmd(1,0x26,0x0000));	
}


void AC97_CodecExit_MICIn(unsigned short DACs_off)
{
	//ADCs off
	printf("\n\n=>ADCs off PR0\n");
	AC97_Codec_Cmd(0,0x26,(1<<8));
	AC97_Controller_State();

⌨️ 快捷键说明

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