目前能夠初始化AC97,能夠進入就緒中斷,說明能夠檢測到WM9714,但是無法讀取WM9714,不知道哪裡出錯了,目前正在解決中...
AC97.c
/*************************************************************************************************************
* 文件名: AC97.c
* 功能: S3C6410 AC97底層驅動函數
* 作者: [email protected]
* 創建時間: 2012年10月6日20:41
* 最後修改時間:2012年10月6日
* 詳細: AC97控制器底層驅動
*************************************************************************************************************/
#include "system.h"
#include "ac97.h"
#include "delay.h"
//使能AC97-LINK傳輸數據
#define AC97_EnTraansferACLink() (AC97->GLBCTRL |= BIT3)
//使能AC97-LINK
#define AC97_ACLinkOn() (AC97->GLBCTRL |= BIT2)
//AC97中斷定義
#define AC97_ALL_INT (0x7f << 16)//全部中斷
#define CODE_READY_INT (1 << 22) //編解碼器准備就緒中斷
#define PCM_OUT_UNDER_INT (1 << 21) //PCM輸出通道FIFO空中斷
#define PCM_IN_OVER_INT (1 << 20) //PCM輸入通道FIFO滿中斷
#define MIC_IN_OVER_INT (1 << 19) //MIC輸入通道FIFO滿中斷
#define PCM_OUT_THRES_INT (1 << 18) //PCM輸出通道FIFO半滿中斷
#define PCM_IN_THRES_INT (1 << 17) //PCM輸入通道FIFO半滿中斷
#define MIC_IN_THRES_INT (1 << 16) //MIC輸入通道FIFO半滿中斷
//延時控制,單位US
#define AC97_WARMRESET_DELAY 2 //系統熱復位延時
#define AC97_COLDRESET_DELAY 2 //系統冷復位延時
#define AC97_CMDREAD_DELAY 2000//讀取延時
#define AC97_CMDWRITE_DELAY 22 //寫命令延時
/*************************************************************************************************************************
*函數 : void AC97_WarmReset(void)
*功能 : AC97控制器熱復位
*參數 : 無
*返回 : 無
*依賴 : 底層宏定義
*作者 : [email protected]
*時間 : 20121006
*最後修改時間: 20121006
*說明 : 用於從關閉電源喚醒編解碼器
*************************************************************************************************************************/
void AC97_WarmReset(void)
{
AC97->GLBCTRL &= ~(0xf); //清除設置
AC97->GLBCTRL |= BIT1; //開始復位
Delay_US(AC97_WARMRESET_DELAY); //延時,大於1US
AC97->GLBCTRL &= ~BIT1; //結束復位
AC97_ACLinkOn();
AC97_EnTraansferACLink();
Delay_US(1);
}
/*************************************************************************************************************************
*函數 : void AC97_ColdReset(void)
*功能 : AC97控制器冷復位
*參數 : 無
*返回 : 無
*依賴 : 底層宏定義
*作者 : [email protected]
*時間 : 20121006
*最後修改時間: 20121006
*說明 : 用於復位編解碼器和控制器的邏輯,復位時間最小1us
*************************************************************************************************************************/
void AC97_ColdReset(void)
{
AC97->GLBCTRL |= BIT0; //開始復位
Delay_US(AC97_COLDRESET_DELAY);
AC97->GLBCTRL &= ~BIT0; //結束復位
AC97_WarmReset();
Delay_US(1);
}
/*************************************************************************************************************************
*函數 : u8 AC97_Init(void)
*功能 : AC97控制器初始化
*參數 : 無
*返回 : 1:初始化失敗;0:初始化成功
*依賴 : 底層宏定義
*作者 : [email protected]
*時間 : 20121006
*最後修改時間: 20121006
*說明 : 無
*************************************************************************************************************************/
u8 AC97_Init(void)
{
u16 i = 0;
//初始化AC97硬件接口
rGPDPUD = 0x1 << 2; //AC97BITCLK CDCLK Pull Down Enable
rGPDCON = 0x44444;
Set_GateClk(PCLK_AC97,ENABLE); //使能AC97控制器門控時鐘
AC97_ColdReset(); //AC97控制器冷復位
AC97_IntClear(CODE_READY_INT); //清除准備就緒中斷
AC97_IntEnable(CODE_READY_INT,ENABLE); //使能准備就緒中斷
while(!(AC97_GetIntStatus() & CODE_READY_INT)) //等待准備就緒中斷
{
i ++;
if(i > 1000)
{
DEBUG("AC97 Waint Time Out!\n");
return 1;
}
Delay_MS(1);
}
AC97_IntEnable(CODE_READY_INT,DISABLE); //關閉准備就緒中斷
AC97_IntClear(CODE_READY_INT); //清除准備就緒中斷
Delay_MS(1);
return 0;
}
/*************************************************************************************************************************
*函數 : u16 AC97_CodeCMD(AC97_CMD AC97_RW,u8 RegAddr,u16 CmdData)
*功能 : AC97讀寫命令控制
*參數 : AC97_RW:讀寫控制,見AC97_CMD;RegAddr:寄存器地址;CmdData:命令數據
*返回 : 無
*依賴 : 底層宏定義
*作者 : [email protected]
*時間 : 20121006
*最後修改時間: 20121006
*說明 : 連續寫命令需要延時,一個命令到下一個命令之間有延時多於1 / 48KHz 大約23US
*************************************************************************************************************************/
u16 AC97_CodeCMD(AC97_CMD AC97_RW,u8 RegAddr,u16 CmdData)
{
if(AC97_RW == AC97_READ) //讀取
{
AC97->CODEC_CMD = (u32)((RegAddr << 16) | (1 << 23) | (0 << 0));
Delay_US(AC97_CMDREAD_DELAY);
return (u16)(AC97->CODEC_STAT & 0xffff);
}
else if(AC97_RW == AC97_WRITE) //寫入
{
AC97->CODEC_CMD = (u32)((RegAddr << 16) | (0 << 23) | (CmdData << 0));
Delay_US(AC97_CMDWRITE_DELAY);
return 0;
}
else
{
DEBUG("AC97 CMD Error!\n");
return 0;
}
}
/*************************************************************************************************************************
*函數 : void AC97_IntEnable(u32 Int,u8 Enable)
*功能 : AC97控制器中斷控制
*參數 : Int:中斷編號,見宏定義;Enable:ENABLE:使能中斷,DISABLE:取消中斷
*返回 : 無
*依賴 : 底層宏定義
*作者 : [email protected]
*時間 : 20121008
*最後修改時間: 20121008
*說明 : 無
*************************************************************************************************************************/
void AC97_IntEnable(u32 Int,u8 Enable)
{
if(Enable == ENABLE) //使能中斷
{
AC97->GLBCTRL |= Int;
}
else //取消中斷
{
AC97->GLBCTRL &= ~Int;
}
}
/*************************************************************************************************************************
*函數 : void AC97_IntClear(u32 Int)
*功能 : AC97控制器中斷清除
*參數 : Int:中斷編號,見宏定義
*返回 : 無
*依賴 : 底層宏定義
*作者 : [email protected]
*時間 : 20121008
*最後修改時間: 20121008
*說明 : 無
*************************************************************************************************************************/
void AC97_IntClear(u32 Int)
{
AC97->GLBCTRL |= (Int << 8); //寫1清除對應中斷
}
/*************************************************************************************************************************
*函數 : u32 AC97_GetIntStatus(void)
*功能 : 獲取AC97中斷狀態
*參數 : 無
*返回 : 中斷狀態
*依賴 : 底層宏定義
*作者 : [email protected]
*時間 : 20121008
*最後修改時間: 20121008
*說明 : 返回的中斷狀態與中斷編號相與
*************************************************************************************************************************/
u32 AC97_GetIntStatus(void)
{
return (AC97->GLBSTAT & (0x7f << 16));
}
/*************************************************************************************************************************
*函數 : AC97_State AC97_GetContStatus(void)
*功能 : 獲取AC97控制器狀態
*參數 : 無
*返回 : 控制器狀態,見AC97_State
*依賴 : 底層宏定義
*作者 : [email protected]
*時間 : 20121009
*最後修改時間: 20121009
*說明 : 無
*************************************************************************************************************************/
AC97_State AC97_GetContStatus(void)
{
return (AC97_State)(AC97->GLBSTAT & 0x07);
}
//AC97控制器中斷服務程序
void __irq Isr_AC97(void)
{
if(AC97->GLBSTAT & CODE_READY_INT) //編解碼器准備就緒中斷
{
}
if(AC97->GLBSTAT & PCM_OUT_UNDER_INT) //PCM輸出通道FIFO空中斷
{
}
if(AC97->GLBSTAT & PCM_IN_OVER_INT) //PCM輸入通道FIFO滿中斷
{
}
if(AC97->GLBSTAT & MIC_IN_OVER_INT) //MIC輸入通道FIFO滿中斷
{
}
if(AC97->GLBSTAT & PCM_OUT_THRES_INT) //PCM輸出通道FIFO半滿中斷
{
}
if(AC97->GLBSTAT & PCM_IN_THRES_INT) //PCM輸入通道FIFO半滿中斷
{
}
if(AC97->GLBSTAT & MIC_IN_THRES_INT) //MIC輸入通道FIFO半滿中斷
{
}
}