📄 wm8753.c
字号:
/*============================================================
File Name: Iis.c
Description: S3C2440A IIS controller Function Test
Version: 0.2
History:
0.0: 2002. 03. 06, Programming Start by SOP.
0.1: 2004. 02. 04, Modified by Y. H. Lee.
- IIS Master Tx: Play Sample Wave File.
- IIS Master Rx: Record Sound using MIC and Play it.
- IIS maser clock selection (PCLK or MPLLin) is supported.
0.2: 2004. 04. 26, Modified by Y. H. Lee.
- Recording Sound via Line-In is available in the SMDK2440 base board (Rev 0.19).
=============================================================*/
#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "profile.h"
#include "usbmain.h"
#include "usbout.h"
#include "usblib.h"
#include "2440usb.h"
#include "nand.h"
#include "iis.h"
#include "wm8753.h"
#define REC_LEN_IIS 0xfffff*2
#define PLAY_IIS 0
#define RECORD_MICIn 1
#define RECORD_LineIn 2
#define L3C (1<<4) //GPB4 = L3CLOCK
#define L3D (1<<3) //GPB3 = L3DATA
#define L3M (1<<2) //GPB2 = L3MODE
//=================
//
//=====================
#define BIT0 0x0001
#define BIT1 1<<1
#define BIT2 0x0004
#define BIT3 1<<3
#define BIT4 1<<4
#define BIT5 0x0020
#define BIT6 0x0040
#define BIT7 0x0080
#define BIT8 0x0100
#define BIT9 0x0200
#define BIT10 0x0400
#define BIT11 0x0800
#define BIT12 0x1000
#define BIT13 0x2000
#define BIT14 0x4000
#define BIT15 0x8000
#define Set_i2c_SDA() rGPBDAT |= BIT3
#define Set_i2c_SCL() rGPBDAT |= BIT4
#define Clr_i2c_SDA() rGPBDAT &= ~BIT3
#define Clr_i2c_SCL() rGPBDAT &= ~BIT4
#define i2c_SDAHi() (rGPBDAT & BIT3)
#define i2c_SDALo() (!(rGPBDAT & BIT3))
#define i2c_SCLHi() (rGPBDAT & BIT4)
#define i2c_SCLLo() (!(rGPBDAT & BIT3))
#define PLL_N 0x7
#define PLL_K 0x23F548
#define WM8753_DEFAULT_HSRATE 48000
#define WM8753_DEFAULT_VSRATE WM8753_VD48K
#define WM8753_I2S_8K 8//SADIV_513K
#define WM8753_I2S_12K 12//SADIV_702K
#define WM8753_I2S_16K 16//SADIV_1_026M
#define WM8753_I2S_22K 22//SADIV_1_405M
#define WM8753_I2S_44K 44//SADIV_2_836M
#define WM8753_I2S_48K 48//SADIV_3_058M
typedef enum i2c_direction
{ I2C_WRITE,
I2C_READ
} I2C_Direction;
//==============================
//
//==============================
char mute = 1;
char which_Buf = 1;
char Rec_Done = 0;
char IIS_MasterClk_Sel = 0;
static U8 hifi = 1;
unsigned char *Buf,*_temp,*Buf2;
unsigned char *rec_buf = (unsigned char *)0x31000000;
unsigned int size, fs;
unsigned int save_B, save_E, save_PB, save_PE;
extern U32 Hclk, Pclk;
extern U8 g_ucWave[155760];
float IIS_Codec_CLK;
void IIS_Port_Init(void);
void IIS_Port_Return(void);
void Download_Wave_File(void);
void Select_IIS_Master_CLK(void);
void IIS_RecSound_DMA1( int mode, U32 rec_size);
void IIS_PlayWave_DMA2(unsigned char *start_addr, U32 play_size);
void _WrL3Addr(U8 data);
void _WrL3Data(U8 data,int halt);
void Open_Wave_File(char *filename);
void Radio_IIS(void);
void __irq RxInt(void);
void __irq Muting(void);
void __irq DMA2_Done(void);
void __irq DMA1_Rec_Done(void);
//=============================
void SDA_pin_out(void);
void SDA_pin_in(void);
void Delay4us(void);
U8 i2c_Start(void);
void i2c_Stop(void);
U8 i2c_SendByte(U8 value, int direction);
U8 i2c_ReceiveByte(const U8 ack);
U8 i2c_BurstWrite(U8 count, U8 *buffer);
U8 i2c_BurstRead(U8 count, U8 * buffer);
U8 i2c_MasterStart(I2C_Direction direct, U8 addr);
int wm8753_i2c_write(unsigned char addr, unsigned char buffer1, unsigned short buffer2);
static U16 reg_cache[64] = {
0x0008, 0x0000, 0x000a, 0x000a,
0x0003, 0x0000, 0x0007, 0x01ff,
0x01ff, 0x000f, 0x000f, 0x007b,
0x0000, 0x0032, 0x0000, 0x00c3,
0x00c3, 0x00c0, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0055,
0x0005, 0x0050, 0x0055, 0x0050,
0x0055, 0x0050, 0x0055, 0x0079,
0x0079, 0x0079, 0x0079, 0x0079,
0x0000, 0x0000, 0x0000, 0x0000,
0x0097, 0x0097, 0x0000, 0x0004,
0x0000, 0x0083, 0x0024, 0x01ba,
0x0000, 0x0083, 0x0024, 0x01ba
};
static unsigned short wav[600*1024];
static int wm8753_init_pll(void)
{
U16 value;
#if 0
if (hifi) {
/* set up N and K PLL divisor ratios */
/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
value = (PLL_N << 5) + ((PLL_K & 0x3c0000) >> 18);
if (wm8753_i2c_write(0x34, WM8753_PLL1CTL2, value) != 0)
return -1;
/* bits 8:0 = PLL_K[17:9] */
value = (PLL_K & 0x03fe00) >> 9;
if (wm8753_i2c_write(0x34, WM8753_PLL1CTL3, value) != 0)
return -1;
/* bits 8:0 = PLL_K[8:0] */
value = PLL_K & 0x0001ff;
if (wm8753_i2c_write(0x34, WM8753_PLL1CTL4, value) != 0)
return -1;
/* set PLL1 as input and enable */
if (wm8753_i2c_write(0x34, WM8753_PLL1CTL1, 0x0027) != 0)
return -1;
}
/* set up N and K PLL divisor ratios */
/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
value = (PLL_N << 5) + ((PLL_K & 0x3c0000) >> 18);
if (wm8753_i2c_write(0x34, WM8753_PLL2CTL2, value) != 0)
return -1;
/* bits 8:0 = PLL_K[17:9] */
value = (PLL_K & 0x03fe00) >> 9;
if (wm8753_i2c_write(0x34, WM8753_PLL2CTL3, value) != 0)
return -1;
/* bits 8:0 = PLL_K[8:0] */
value = PLL_K & 0x0001ff;
if (wm8753_i2c_write(0x34, WM8753_PLL2CTL4, value) != 0)
return -1;
/* set PLL2 as input and enable */
if (wm8753_i2c_write(0x34, WM8753_PLL2CTL1, 0x0027) != 0)
return -1;
/* now enable the clock */
if (wm8753_i2c_write(0x34, WM8753_CLOCK, WM8753_DEFAULT_VSRATE | 0x18) != 0)
return -1;
if (wm8753_i2c_write(0x34, WM8753_INCTL1, 0x0007) != 0)
return -1;
#endif
if (wm8753_i2c_write(0x34, WM8753_INCTL1, 0x0007) != 0) //0x0007
return 0;
}
/*
* Power up the codec
*/
static int wm8753_power_up(void)
{
U16 pwr = 0xf0;
if (hifi)
pwr |= 0xc;
/* set Vmid to 5kOhm, enable VREF and VDAC */
if (wm8753_i2c_write(0x34, WM8753_PWR1, 0x0100 | pwr) != 0)
return -1; //-- 0x100 | pwr
/* enable MIC1 preamp, ALC mix and left ADC */
if (wm8753_i2c_write(0x34, WM8753_PWR2, 0x01ff) != 0)
return -1; //0x0168
/* enable LOUT 1, ROUT1, MONO1 */ //0x0184
/* enable LOUT 1, ROUT1, MONO1 LOUT 2 ROUT2 */ //0x01E4
if (wm8753_i2c_write(0x34, WM8753_PWR3, 0x01ff) != 0)
return -1; //0x184
/* enable left, right mono mixer */
if (wm8753_i2c_write(0x34, WM8753_PWR4, 0x000f) != 0)
return -1; //0x000b
/* let WM8753 powerup and then set Vmid to 50kOhm */
Delay(10000);
if (wm8753_i2c_write(0x34, WM8753_PWR1, pwr) != 0)
return -1;
return 0;
}
static int wm8753_power_down()
{
if ((wm8753_i2c_write(0x34, WM8753_PWR1, 0x0100) != 0) &&
(wm8753_i2c_write(0x34, WM8753_PWR2, 0x0000) != 0) &&
(wm8753_i2c_write(0x34, WM8753_PWR3, 0x0000) != 0) &&
(wm8753_i2c_write(0x34, WM8753_PWR4, 0x0000) != 0)) {
Uart_Printf("could not powerdown WM8753");
return -1;
}
return 0;
}
/*
* Set WM8753 ADC and DAC sample rates and
* enable SSP port 2 at the correct speed.
*
* returns sample rate on success, else error.
*/
static U16 wm8753_read_reg_cache(U8 reg)
{
return reg_cache[reg - 1];
}
static int wm8753_i2s_open(int speed)
{
// CKEN |= CKEN8_I2S;
rCLKCON |= (1<<17);
/*
SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1) | SACR0_BCKD;
SACR1 &= ~(SACR1_DRPL | SACR1_DREC | SACR1_AMSL);
SAIMR |= SAIMR_RFS | SAIMR_TFS;
SADIV = speed;
SACR0 |= SACR0_ENB;
*/
return 0;
}
static void wm8753_i2s_close()
{
// SACR0 &= ~SACR0_ENB;
// CKEN &= ~CKEN8_I2S;
rCLKCON &=~(1<<17);
rIISCON &=~(1<<0);
}
/*
void ssp_enable(void)
{
Ser4SSCR0 |= SSCR0_SSE;
}
*/
static int wm8753_set_adcdac_rate(int val)
{
int ret = val;
U16 clock;
clock = wm8753_read_reg_cache(WM8753_CLOCK) & 0x3f;
switch (val) {
case 8000: /* ADC/DAC 8kHz */
if (wm8753_i2c_write(0x34, WM8753_SRATE1, WM8753_A8D8) != 0)
ret = -1;
if (wm8753_i2c_write(0x34, WM8753_CLOCK, WM8753_VD8K | clock) !=0)
ret = -1;
// if (wm8753_psp_open(WM8753_SSP_8K) != 0)
// ret = -1;
if (hifi)
wm8753_i2s_open(WM8753_I2S_8K);
break;
case 12000: /* ADC/DAC 12kHz */
if (wm8753_i2c_write(0x34, WM8753_SRATE1, WM8753_A12D12) != 0)
ret = -1;
if (wm8753_i2c_write(0x34, WM8753_CLOCK, WM8753_VD12K | clock) !=0)
ret = -1;
// if (wm8753_psp_open(WM8753_SSP_12K) != 0)
// ret = -1;
if (hifi)
wm8753_i2s_open(WM8753_I2S_12K);
break;
case 16000: /* ADC/DAC 16kHz */
if (wm8753_i2c_write(0x34, WM8753_SRATE1, WM8753_A16D16) != 0)
ret = -1;
if (wm8753_i2c_write(0x34, WM8753_CLOCK, WM8753_VD16K | clock) !=0)
ret = -1;
// if (wm8753_psp_open(WM8753_SSP_16K) != 0)
// ret = -1;
if (hifi)
wm8753_i2s_open(WM8753_I2S_16K);
break;
case 24000: /* ADC/DAC 24kHz - Voice DAC only*/
if (wm8753_i2c_write(0x34, WM8753_SRATE1, WM8753_A24D24) != 0)
ret = -1;
if (wm8753_i2c_write(0x34, WM8753_CLOCK, WM8753_VD24K | clock) !=0)
ret = -1;
// if (wm8753_psp_open(WM8753_SSP_24K) != 0)
// ret = -1;
break;
case 48000: /* ADC/DAC 48kHz */
if (wm8753_i2c_write(0x34, WM8753_SRATE1, WM8753_A48D48) != 0)
ret = -1;
if (wm8753_i2c_write(0x34, WM8753_CLOCK, WM8753_VD48K | clock) !=0)
ret = -1;
// if (wm8753_psp_open(WM8753_SSP_48K) != 0)
// ret = -1;
if (hifi)
wm8753_i2s_open(WM8753_I2S_48K);
break;
default:
/* desired rate is not permitted */
ret = -1;
break;
}
// if (ret != -1)
// ssp_enable(&wm8753_codec.ssp);
return ret;
}
static int wm8753_init(void)
{
int ret = 0;
/*
while(1){
Set_i2c_SCL();
Delay4us();
Clr_i2c_SCL();
Delay4us();
}
while(1){
wm8753_power_up();
}
*/ /* power up the device */
if ((ret = wm8753_power_up()) != 0) {
ret = -1;
goto out;
}
/* start adc/dac clocks */
if ((ret = wm8753_init_pll()) != 0) {
Uart_Printf("could not initialise PLL's\n");
ret = -1;
goto out;
}
/* set up GPIO and alternate functions for SSP2/I2S
set_GPIO_mode(GPIO13_SSP2TX_MD);
set_GPIO_mode(GPIO22_SSP2CLK_MD);
set_GPIO_mode(GPIO86_SSP2RX_MD); // not sure of correct GPIO for SSP2 RX
set_GPIO_mode(GPIO88_SSP2FRM_MD);
if (hifi) {
set_GPIO_mode(GPIO29_SDATA_IN_I2S_MD);
set_GPIO_mode(28 | GPIO_ALT_FN_1_OUT);
set_GPIO_mode(GPIO30_SDATA_OUT_I2S_MD);
set_GPIO_mode(GPIO31_SYNC_I2S_MD);
}
*/
/* set up default ADC/DAC sample rate */
if ((ret = wm8753_set_adcdac_rate(WM8753_DEFAULT_HSRATE)) != WM8753_DEFAULT_HSRATE) {
Uart_Printf("could not set WM8753 sample rate to %d", WM8753_DEFAULT_HSRATE);
ret = -1;
goto out;
}
/* set up ADC mode */
ret = wm8753_i2c_write(0x34, WM8753_ADC, 0x001c);
/* set up sample rate mode 87*/
ret += wm8753_i2c_write(0x34, WM8753_SRATE2, 0x0097);
/* set up PCM digital interface format and master mode */
ret += wm8753_i2c_write(0x34, WM8753_PCM, 0x0063);
/* set up PCM digital interface as output */
ret += wm8753_i2c_write(0x34, WM8753_IOCTL, 0x0003);
//0x0003
ret += wm8753_i2c_write(0x34, WM8753_INCTL1, 0x0000); //0x0007
/* set up default input audio paths, enable MIC1 */
ret += wm8753_i2c_write(0x34, WM8753_INCTL2, 0x0000);
//0x0002 ----hxm
/* set up analog mono mix using LADC */
// ret += wm8753_i2c_write(0x34, WM8753_ADCIN, 0x0011);
//0x0010 ---hxm
/* set up left input PGA */
ret += wm8753_i2c_write(0x34, WM8753_LINVOL, 0x011c);
/* set up default output audio paths, enable left out 1 */
// ret += wm8753_i2c_write(0x34, WM8753_LOUTM1, 0x0103);
ret += wm8753_i2c_write(0x34, WM8753_LOUTM1, 0x0180);
/* set up default output audio paths, enable rightt out 1 */
// ret += wm8753_i2c_write(0x34, WM8753_ROUTM1, 0x0103);
ret += wm8753_i2c_write(0x34, WM8753_ROUTM1, 0x0180);
/* set up default output audio paths, enable left out 2 */
// ret += wm8753_i2c_write(0x34, WM8753_LOUTM2, 0x0103);
ret += wm8753_i2c_write(0x34, WM8753_LOUTM2, 0x0180);
/* set up default output audio paths, enable rightt out 2 */
// ret += wm8753_i2c_write(0x34, WM8753_ROUTM2, 0x0103);
ret += wm8753_i2c_write(0x34, WM8753_ROUTM2, 0x0100);
ret += wm8753_i2c_write(0x34, WM8753_LOUT2V, 0x017F); /* set up default output audio paths, enable right out 2 */
ret += wm8753_i2c_write(0x34, WM8753_ROUT2V, 0x017F); /* set up default output audio paths, enable right out 2 */
/*ROUT2INV enable*/
ret +=wm8753_i2c_write(0x34, WM8753_OUTCTL, 0x0106);
/* set up default output audio paths, enable mono 1 */
ret += wm8753_i2c_write(0x34, WM8753_MOUTM2, 0x005a);
/* hifi stuff */
if (hifi == 0)
goto out;
/* enable hifi DAC */
ret += wm8753_i2c_write(0x34, WM8753_HIFI, 0x0002);
/* enable Left mixer */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -