diff options
Diffstat (limited to 'uClinux-2.4.20-uc1/drivers/sound')
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.c | 1674 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.h | 120 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/sound/w90n745_audio.h | 290 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/sound/w90n745_audio_regs.h | 398 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.c | 1354 | ||||
-rw-r--r-- | uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.h | 138 |
6 files changed, 1987 insertions, 1987 deletions
diff --git a/uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.c b/uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.c index fb58349..297c90e 100644 --- a/uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.c +++ b/uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.c @@ -1,837 +1,837 @@ -/****************************************************************************
- *
- * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved.
- *
- *
- * FILENAME
- * w90n745_AC97.c
- *
- * VERSION
- * 1.2
- *
- * DESCRIPTION
- * AC97 interface for W83972D codec
- *
- * DATA STRUCTURES
- * None
- *
- * FUNCTIONS
- * ...
- *
- * HISTORY
- * 2004.06.01 Created by Yung-Chang Huang
- * 2004.09.02 Ver 1.0 Modify for w90n745 coding standard
- * 2005.11.24 Ver 1.1 Modified for uCLinux Sound Driver by PC34 QFu
- * 2006.01.17 Ver 1.2 Modified for w90n745 Version B
- *
- * REMARK
- * None
- *
- **************************************************************************/
-#include <linux/soundcard.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "w90n745_audio_regs.h"
-#include "w90n745_audio.h"
-#include "w90n745_ac97.h"
-
-//#define AC97_DEBUG
-//#define AC97_DEBUG_ENTER_LEAVE
-//#define AC97_DEBUG_MSG
-//#define AC97_DEBUG_MSG2
-
-#ifdef AC97_DEBUG
-#define DBG(fmt, arg...) printk(fmt, ##arg)
-#else
-#define DBG(fmt, arg...)
-#endif
-
-#ifdef AC97_DEBUG_ENTER_LEAVE
-#define ENTER() DBG("[%-10s] : Enter\n", __FUNCTION__)
-#define LEAVE() DBG("[%-10s] : Leave\n", __FUNCTION__)
-#else
-#define ENTER()
-#define LEAVE()
-#endif
-
-#ifdef AC97_DEBUG_MSG
-#define MSG(fmt) DBG("[%-10s] : "fmt, __FUNCTION__)
-#else
-#define MSG(fmt)
-#endif
-
-#ifdef AC97_DEBUG_MSG2
-#define MSG2(fmt, arg...) DBG("[%-10s] : "fmt, __FUNCTION__, ##arg)
-#else
-#define MSG2(fmt, arg...)
-#endif
-
-#define AUDIO_WRITE(addr, val) writel(val, addr)
-#define AUDIO_READ(addr) readl(addr)
-
-static AUDIO_T _tAC97;
-
-static int _bAC97Active = 0;
-static volatile int _bPlayDmaToggle, _bRecDmaToggle;
-
-static void ac97StopPlay(void);
-
-struct semaphore ac97_sem;
-
-static unsigned int ac97_read_register(INT nIdx)
-{
- volatile INT nWait;
- unsigned int i;
-
- down(&ac97_sem);
-
- /* set the R_WB bit and write register index */
- AUDIO_WRITE(REG_ACTL_ACOS1, 0x80 | nIdx);
-
- /* set the valid frame bit and valid slots */
- AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) |0x11);
-
- udelay(100);
-
- /* polling the AC_R_FINISH */
- for (nWait = 0; nWait < 0x10000; nWait++)
- {
- if (AUDIO_READ(REG_ACTL_ACCON) & AC_R_FINISH)
- break;
- }
- if (nWait == 0x10000)
- MSG("ac97_read_register time out!\n");
-
- AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) & ~1);
-
- if (AUDIO_READ(REG_ACTL_ACIS1) >> 2 != nIdx)
- { MSG2("ac97_read_register - R_INDEX of REG_ACTL_ACIS1 not match!, 0x%x\n", AUDIO_READ(REG_ACTL_ACIS1)); }
-
- udelay(100);
- i = AUDIO_READ(REG_ACTL_ACIS2) & 0xFFFF;
-
- up(&ac97_sem);
- return (i);
-}
-
-
-static int ac97_write_register(INT nIdx, UINT16 sValue)
-{
- volatile INT nWait;
-
- down(&ac97_sem);
-
- /* clear the R_WB bit and write register index */
- AUDIO_WRITE(REG_ACTL_ACOS1, nIdx);
-
- /* write register value */
- AUDIO_WRITE(REG_ACTL_ACOS2, (UINT32)sValue);
-
- /* set the valid frame bit and valid slots */
- AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) | 0x13);
-
- udelay(100);
-
- /* polling the AC_W_FINISH */
- for (nWait = 0; nWait < 0x10000; nWait++)
- {
- if (!(AUDIO_READ(REG_ACTL_ACCON) & AC_W_FINISH))
- break;
- }
-
- AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) & ~3);
-
- up(&ac97_sem);
-
-
- // paraniod?
- //if (ac97_read_register(nIdx) != sValue)
- // MSG2("ac97_write_register, nIdx=0x%x, mismatch, 0x%x must be 0x%x\n", nIdx, ac97_read_register(nIdx), sValue);
-
- return 0;
-}
-
-#if 0
-static void ac97_read_all_registers()
-{
- MSG("AC97_RESET = 0x%04x\n", ac97_read_register(AC97_RESET));
- MSG("AC97_MASTER_VOLUME = 0x%04x\n", ac97_read_register(AC97_MASTER_VOLUME));
- MSG("AC97_AUX_OUT_VOLUME = 0x%04x\n", ac97_read_register(AC97_AUX_OUT_VOLUME));
- MSG("AC97_MONO_VOLUME = 0x%04x\n", ac97_read_register(AC97_MONO_VOLUME));
- MSG("AC97_MASTER_TONE = 0x%04x\n", ac97_read_register(AC97_MASTER_TONE));
- MSG("AC97_PC_BEEP_VOLUME = 0x%04x\n", ac97_read_register(AC97_PC_BEEP_VOLUME));
- MSG("AC97_PHONE_VOLUME = 0x%04x\n", ac97_read_register(AC97_PHONE_VOLUME));
- MSG("AC97_MIC_VOLUME = 0x%04x\n", ac97_read_register(AC97_MIC_VOLUME));
- MSG("AC97_LINE_IN_VOLUME = 0x%04x\n", ac97_read_register(AC97_LINE_IN_VOLUME));
- MSG("AC97_CD_VOLUME = 0x%04x\n", ac97_read_register(AC97_CD_VOLUME));
- MSG("AC97_VIDEO_VOLUME = 0x%04x\n", ac97_read_register(AC97_VIDEO_VOLUME));
- MSG("AC97_AUX_IN_VOLUME = 0x%04x\n", ac97_read_register(AC97_AUX_IN_VOLUME));
- MSG("AC97_PCM_OUT_VOLUME = 0x%04x\n", ac97_read_register(AC97_PCM_OUT_VOLUME));
- MSG("AC97_RECORD_SELECT = 0x%04x\n", ac97_read_register(AC97_RECORD_SELECT));
- MSG("AC97_RECORD_GAIN = 0x%04x\n", ac97_read_register(AC97_RECORD_GAIN));
- MSG("AC97_RECORD_GAIN_MIC = 0x%04x\n", ac97_read_register(AC97_RECORD_GAIN_MIC));
- MSG("AC97_GENERAL_PURPOSE = 0x%04x\n", ac97_read_register(AC97_GENERAL_PURPOSE));
- MSG("AC97_3D_CONTROL = 0x%04x\n", ac97_read_register(AC97_3D_CONTROL));
- MSG("AC97_AUDIO_INT_PAGING = 0x%04x\n", ac97_read_register(AC97_AUDIO_INT_PAGING));
- MSG("AC97_POWERDOWN_CTRL = 0x%04x\n", ac97_read_register(AC97_POWERDOWN_CTRL));
- MSG("AC97_FRONT_DAC_RATE = 0x%04x\n", ac97_read_register(AC97_FRONT_DAC_RATE));
-}
-#endif
-
-static void ac97_play_isr(void)
-{
- int bPlayLastBlock;
-
- ENTER();
-
- if(!(AUDIO_READ(REG_ACTL_CON) & T_DMA_IRQ))
- return;
-
- AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ(REG_ACTL_CON) | T_DMA_IRQ);
-
- if (_bPlayDmaToggle == 0)
- {
- if (AUDIO_READ(REG_ACTL_PSR) & P_DMA_MIDDLE_IRQ)
- AUDIO_WRITE(REG_ACTL_PSR, P_DMA_MIDDLE_IRQ);
- else
- MSG("ac97_play_isr - miss middle!\n");
-
- _bPlayDmaToggle = 1;
-
- bPlayLastBlock = _tAC97.fnPlayCallBack(_tAC97.uPlayBufferAddr,
- _tAC97.uPlayBufferLength/2);
- }
- else
- {
- if (AUDIO_READ(REG_ACTL_PSR) & P_DMA_END_IRQ)
- AUDIO_WRITE(REG_ACTL_PSR, P_DMA_END_IRQ);
- else
- MSG("ac97_play_isr - miss end!\n");
-
- _bPlayDmaToggle = 0;
-
- bPlayLastBlock = _tAC97.fnPlayCallBack(_tAC97.uPlayBufferAddr+ _tAC97.uPlayBufferLength/ 2,
- _tAC97.uPlayBufferLength/2);
- }
-
-
- /* here, we will check whether the next buffer is ready. If not, stop play. */
- if (bPlayLastBlock)
- AUDIO_WRITE(REG_ACTL_PSR, P_DMA_MIDDLE_IRQ | P_DMA_END_IRQ);
-
-
- LEAVE();
-
-}
-
-
-static void ac97_rec_isr(void)
-{
- int bPlayLastBlock;
-
- ENTER();
-
- if(!(AUDIO_READ(REG_ACTL_CON) & R_DMA_IRQ))
- return;
-
- AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ(REG_ACTL_CON) | R_DMA_IRQ);
-
- if (_bRecDmaToggle == 0)
- {
- if (AUDIO_READ(REG_ACTL_RSR) & R_DMA_MIDDLE_IRQ)
- AUDIO_WRITE(REG_ACTL_RSR, R_DMA_MIDDLE_IRQ);
- else
- MSG("ac97_rec_isr - miss middle!\n");
-
- _bRecDmaToggle = 1;
- bPlayLastBlock = _tAC97.fnRecCallBack(_tAC97.uRecordBufferAddr,
- _tAC97.uRecordBufferLength/2);
- }
- else
- {
- if (AUDIO_READ(REG_ACTL_RSR) & R_DMA_END_IRQ)
- AUDIO_WRITE(REG_ACTL_RSR, R_DMA_END_IRQ);
- else
- MSG("ac97_rec_isr - miss end!\n");
-
- _bRecDmaToggle = 0;
- bPlayLastBlock = _tAC97.fnRecCallBack(_tAC97.uRecordBufferAddr + _tAC97.uRecordBufferLength / 2,
- _tAC97.uRecordBufferLength /2);
- }
-
- if (bPlayLastBlock)
- AUDIO_WRITE(REG_ACTL_RSR, R_DMA_MIDDLE_IRQ | R_DMA_END_IRQ);
-
- LEAVE();
-}
-
-static int ac97_reset(void)
-{
- ENTER();
-
- AUDIO_WRITE(REG_CLKSEL, AUDIO_READ(REG_CLKSEL) | 0x10000);
-
- AUDIO_WRITE(0xFFF83000,0x155);//GPIO_CFG0 PT0CFG0~4
- AUDIO_WRITE(0xFFF83004,0xd);//GPIO4,1:In GPIO0,2,3:Out
-
- //AUDIO_WRITE(REG_GPIOA_OE, (AUDIO_READ(REG_GPIOA_OE) & 0xFFFFC0FF) | 0x2700);
-
- /* disable pull-high/low */
- //AUDIO_WRITE(REG_GPIOA_PE, 0x3F00);
-
- udelay(1000);
-
- _tAC97.sPlayVolume = 0x0000;
- _tAC97.sRecVolume = 0x0000;
-
- /* enable audio controller and AC-link interface */
- AUDIO_WRITE(REG_ACTL_CON, IIS_AC_PIN_SEL | AUDIO_EN | ACLINK_EN | PFIFO_EN | RFIFO_EN | T_DMA_IRQ | R_DMA_IRQ | DMA_EN);
- udelay(1000);
-
- /* reset Audio Controller */
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | ACTL_RESET_BIT);
- udelay(1000);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~ACTL_RESET_BIT);
- udelay(1000);
-
- /* reset AC-link interface */
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | AC_RESET);
- udelay(1000);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~AC_RESET);
- udelay(1000);
-
-
- /* cold reset AC 97 */
- AUDIO_WRITE(REG_ACTL_ACCON, AUDIO_READ(REG_ACTL_ACCON) | AC_C_RES);
- udelay(1000);
- AUDIO_WRITE(REG_ACTL_ACCON, AUDIO_READ(REG_ACTL_ACCON) & ~AC_C_RES);
- udelay(1000);
-
-
- if (!(AUDIO_READ(REG_ACTL_ACIS0) & 0x10))
- {
- MSG("Error - AC97 codec ready was not set, cold reset failed!\n");
- return ERR_AC97_CODEC_RESET;
- }
-
- udelay(100);
- //ac97_read_all_registers();
-
- /* set volumes */
-
- ac97_write_register(AC97_MASTER_VOLUME, _tAC97.sPlayVolume);
-
- ac97_write_register(AC97_MONO_VOLUME, 0x000f);
- //ac97_write_register(AC97_MASTER_TONE, 0x0303);
- ac97_write_register(AC97_MIC_VOLUME, 0x8000);
- //ac97_write_register(AC97_LINE_IN_VOLUME, 0x0707);
- //ac97_write_register(AC97_AUX_IN_VOLUME, 0x0707);
- ac97_write_register(AC97_PCM_OUT_VOLUME, _tAC97.sPlayVolume);
-
- ac97_write_register(AC97_RECORD_SELECT, 0); /* record select MIC in */
- ac97_write_register(AC97_RECORD_GAIN, 0x0404);
- ac97_write_register(AC97_RECORD_GAIN_MIC, 0x0004);
- ac97_write_register(AC97_GENERAL_PURPOSE, 0);
-
- LEAVE();
-
- return 0;
-}
-
-static VOID ac97SetPlaySampleRate(INT nSamplingRate)
-{
- ENTER();
-
- /* set play sampling rate */
- if (nSamplingRate != 48000)
- {
- /* enable VRA and set sampling frequency */
- ac97_write_register(AC97_EXT_AUDIO_CTRL, ac97_read_register(AC97_EXT_AUDIO_CTRL)|0x1);
- ac97_write_register(AC97_FRONT_DAC_RATE, nSamplingRate);
- }
-
- _tAC97.nPlaySamplingRate = nSamplingRate;
-
- LEAVE();
-}
-
-static VOID ac97SetRecordSampleRate(INT nSamplingRate)
-{
- ENTER();
-
- /* set record sampling rate */
- if (nSamplingRate != 48000)
- {
- /* enable VRA and set sampling frequency */
- ac97_write_register(AC97_EXT_AUDIO_CTRL, ac97_read_register(AC97_EXT_AUDIO_CTRL)|0x1);
- ac97_write_register(AC97_LR_ADC_RATE, nSamplingRate);
- }
-
- _tAC97.nRecSamplingRate = nSamplingRate;
-
- LEAVE();
-}
-
-static VOID ac97SetPlayCallBackFunction(AU_CB_FUN_T fnCallBack)
-{
- ENTER();
-
- _tAC97.fnPlayCallBack = fnCallBack;
-
- LEAVE();
-}
-
-static VOID ac97SetRecordCallBackFunction(AU_CB_FUN_T fnCallBack)
-{
- ENTER();
-
- _tAC97.fnRecCallBack = fnCallBack;
-
- LEAVE();
-}
-
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* ac97SetPlayVolume */
-/* */
-/* DESCRIPTION */
-/* Set AC97 left and right channel play volume. */
-/* */
-/* INPUTS */
-/* ucLeftVol play volume of left channel */
-/* ucRightVol play volume of left channel */
-/* 0: mute */
-/* 1: minimal volume */
-/* 31: maxmum volume */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static int ac97SetPlayVolume(UINT32 ucLeftVol, UINT32 ucRightVol)
-{
- int nLData, nRData;
-
- ENTER();
-
- //MSG2("Set AC97 volume to : %d-%d\n", ucLeftVol, ucRightVol);
-
- if (ucLeftVol == 0)
- nLData = 0x80;
- else
- nLData = 31 - (ucLeftVol & 0x1f);
-
- if (ucRightVol == 0)
- nRData = 0x80;
- else
- nRData = 31 - (ucRightVol & 0x1f);
-
- _tAC97.sPlayVolume = (nLData << 8) | nRData;
- ac97_write_register(AC97_PCM_OUT_VOLUME, (nLData << 8) | nRData);
- //ac97_write_register(AC97_PCM_OUT_VOLUME, 0x101);
-
- if (ucLeftVol == 0)
- nLData = 0x80;
- else
- nLData = 62 - ucLeftVol*2;
-
- if (ucRightVol == 0)
- nRData = 0x80;
- else
- nRData = 62 - ucRightVol*2;
-
- ac97_write_register(AC97_AUX_OUT_VOLUME, (nLData << 8) | nRData);
- ac97_write_register(AC97_MASTER_VOLUME, (nLData << 8) | nRData);
-
- MSG2("AC97_MASTER_VOLUME = 0x%04x\r\n", ac97_read_register(AC97_MASTER_VOLUME));
- MSG2("AC97_AUX_OUT_VOLUME = 0x%04x\r\n", ac97_read_register(AC97_AUX_OUT_VOLUME));
- MSG2("AC97_PCM_OUT_VOLUME = 0x%04x\r\n", ac97_read_register(AC97_PCM_OUT_VOLUME));
-#if 0
- down(&ac97_sem);
- if (_bAC97Active & AC97_PLAY_ACTIVE)
- AUDIO_WRITE(REG_ACTL_ACOS0, 0x1f);
- else
- AUDIO_WRITE(REG_ACTL_ACOS0, 0);
- up(&ac97_sem);
-#endif
- LEAVE();
-
- return 0;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* ac97SetRecordVolume */
-/* */
-/* DESCRIPTION */
-/* Set AC97 left and right channel record volume. */
-/* */
-/* INPUTS */
-/* ucLeftVol record volume of left channel */
-/* ucRightVol record volume of left channel */
-/* 0: mute */
-/* 1: minimal volume */
-/* 31: maxmum volume */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static int ac97SetRecordVolume(UINT32 ucLeftVol, UINT32 ucRightVol)
-{
- //INT nStatus;
-
- ENTER();
-
- if (ucLeftVol == 0)
- ucLeftVol = 0x80;
- else
- ucLeftVol = 32 - (ucLeftVol & 0x1f);
-
- if (ucRightVol == 0)
- ucRightVol = 0x80;
- else
- ucRightVol = 32 - (ucRightVol & 0x1f);
-
- _tAC97.sRecVolume = (ucLeftVol << 8) | ucRightVol;
-
- ac97_write_register(AC97_MIC_VOLUME, ucRightVol );
-
- //ac97_read_all_registers();
- LEAVE();
-
- return 0;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* ac97StartPlay */
-/* */
-/* DESCRIPTION */
-/* Start AC97 playback. */
-/* */
-/* INPUTS */
-/* fnCallBack client program provided callback function. The audio */
-/* driver will call back to get next block of PCM data */
-/* nSamplingRate the playback sampling rate. Supported sampling */
-/* rate are 48000, 44100, 32000, 24000, 22050, 16000, */
-/* 11025, and 8000 Hz */
-/* nChannels number of playback nChannels */
-/* 1: single channel, otherwise: double nChannels */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static int ac97StartPlay(AU_CB_FUN_T fnCallBack, INT nSamplingRate, INT nChannels)
-{
- INT nStatus;
-
- ENTER();
-
- if (_bAC97Active & AC97_PLAY_ACTIVE)
- return ERR_AC97_PLAY_ACTIVE; /* AC97 was playing */
-
-
- if (_bAC97Active == 0)
- {
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~PLAY_LEFT_CHNNEL &~PLAY_RIGHT_CHNNEL);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | PLAY_RIGHT_CHNNEL);
- if (nChannels != 1)
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | PLAY_LEFT_CHNNEL);
-
- nStatus = ac97_reset();
- if (nStatus < 0)
- return nStatus;
- }
-
- /* disable by Qfu , for the installation of irq has been done in wb_audio.c
- the only thing to do is to enable irq by this routine */
- Enable_Int(AU_PLAY_INT_NUM);
-
- /* set play sampling rate */
- ac97SetPlaySampleRate(nSamplingRate);
- ac97SetPlayCallBackFunction(fnCallBack);
-
- /* set DMA play destination base address */
- AUDIO_WRITE(REG_ACTL_PDSTB, _tAC97.uPlayBufferAddr);
-
- /* set DMA play buffer length */
- AUDIO_WRITE(REG_ACTL_PDST_LENGTH, _tAC97.uPlayBufferLength);
-
- /* start playing */
- MSG("AC97 start playing...\n");
- _bPlayDmaToggle = 0;
- down(&ac97_sem);
- AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) | 0x1C);
- up(&ac97_sem);
- AUDIO_WRITE(REG_ACTL_PSR, 0x3);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | AC_PLAY);
- _bAC97Active |= AC97_PLAY_ACTIVE;
-
- LEAVE();
-
- return 0;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* ac97StopPlay */
-/* */
-/* DESCRIPTION */
-/* Stop AC97 playback immdediately. */
-/* */
-/* INPUTS */
-/* None */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static void ac97StopPlay(void)
-{
- ENTER();
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(PLAY_RIGHT_CHNNEL | PLAY_LEFT_CHNNEL));
-
- if (!(_bAC97Active & AC97_PLAY_ACTIVE))
- return;
-
-
- //ac97_read_all_registers ();
-
- /* stop playing */
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~AC_PLAY);
-
- down(&ac97_sem);
- AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) & ~0xC);
- up(&ac97_sem);
-
-
- _bAC97Active &= ~AC97_PLAY_ACTIVE;
- /* disable audio play interrupt */
- if (!_bAC97Active)
- Disable_Int(AU_PLAY_INT_NUM);
-
-
- LEAVE();
-
- return;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* ac97StartRecord */
-/* */
-/* DESCRIPTION */
-/* Start AC97 record. */
-/* */
-/* INPUTS */
-/* fnCallBack client program provided callback function. The audio */
-/* driver will call back to deliver the newly recorded */
-/* block of PCM data */
-/* nSamplingRate the record sampling rate. Supported sampling */
-/* rate are 48000, 44100, 32000, 24000, 22050, 16000, */
-/* 11025, and 8000 Hz */
-/* nChannels number of record nChannels */
-/* 1: single channel, otherwise: double nChannels */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static int ac97StartRecord(AU_CB_FUN_T fnCallBack, INT nSamplingRate, INT nChannels)
-{
- INT nStatus;
- unsigned int i;
-
- ENTER();
-
- if (_bAC97Active & AC97_REC_ACTIVE)
- return ERR_AC97_REC_ACTIVE; /* AC97 was recording */
-
- if (_bAC97Active == 0)
- {
-
- nStatus = ac97_reset();
- if (nStatus < 0)
- return nStatus;
- }
-
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~RECORD_RIGHT_CHNNEL &~RECORD_LEFT_CHNNEL);
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | RECORD_RIGHT_CHNNEL);
- if (nChannels != 1) {
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | RECORD_LEFT_CHNNEL);
- }
-
-
-
-
- /* enable AC97 record interrupt */
- Enable_Int(AU_REC_INT_NUM);
-
-
-
- /* set record sampling rate */
- ac97SetRecordSampleRate(nSamplingRate);
- ac97SetRecordCallBackFunction(fnCallBack);
-
-
- /* set DMA record destination base address */
- AUDIO_WRITE(REG_ACTL_RDSTB, _tAC97.uRecordBufferAddr);
-
- /* set DMA record buffer length */
- AUDIO_WRITE(REG_ACTL_RDST_LENGTH, _tAC97.uRecordBufferLength);
-
- /* start recording */
- MSG("AC97 start recording...\n");
- _bRecDmaToggle = 0;
- AUDIO_WRITE(REG_ACTL_RSR, 0x3);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | AC_RECORD);
- _bAC97Active |= AC97_REC_ACTIVE;
-
- LEAVE();
-
- return 0;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* ac97StopRecord */
-/* */
-/* DESCRIPTION */
-/* Stop AC97 record immediately. */
-/* */
-/* INPUTS */
-/* None */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static void ac97StopRecord(void)
-{
- ENTER();
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(RECORD_RIGHT_CHNNEL | RECORD_LEFT_CHNNEL));
-
- if (!(_bAC97Active & AC97_REC_ACTIVE))
- return;
-
- //ac97_read_all_registers ();
- /* stop recording */
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~AC_RECORD);
-
- _bAC97Active &= ~AC97_REC_ACTIVE;
- /* disable audio record interrupt */
- if (!_bAC97Active)
- Disable_Int(AU_PLAY_INT_NUM);
-
-
- LEAVE();
-
- return;
-}
-
-static void ac97SetPlayBuffer(UINT32 uDMABufferAddr, UINT32 uDMABufferLength)
-{
- ENTER();
-
- _tAC97.uPlayBufferAddr = uDMABufferAddr;
- _tAC97.uPlayBufferLength = uDMABufferLength;
-
- LEAVE();
-}
-
-static void ac97SetRecordBuffer(UINT32 uDMABufferAddr, UINT32 uDMABufferLength)
-{
- ENTER();
-
- _tAC97.uRecordBufferAddr = uDMABufferAddr;
- _tAC97.uRecordBufferLength = uDMABufferLength;
-
- LEAVE();
-}
-
-
-static INT ac97Init(VOID)
-{
- int nStatus = 0;
-
- ENTER();
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~PLAY_LEFT_CHNNEL &~PLAY_RIGHT_CHNNEL);
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~RECORD_LEFT_CHNNEL &~RECORD_RIGHT_CHNNEL);
-
- nStatus = ac97_reset();
- if (nStatus < 0)
- return nStatus;
-
- LEAVE();
-
- return 0;
-}
-
-static INT ac97GetCapacity(VOID)
-{
- return DSP_CAP_DUPLEX; /* support full duplex */
-}
-
-WB_AUDIO_CODEC_T wb_ac97_codec = {
- dev: AU_DEV_AC97,
- get_capacity: ac97GetCapacity,
- set_play_buffer: ac97SetPlayBuffer,
- set_record_buffer: ac97SetRecordBuffer,
- reset: ac97Init,
- start_play: ac97StartPlay,
- stop_play: ac97StopPlay,
- start_record: ac97StartRecord,
- stop_record: ac97StopRecord,
- set_play_volume: ac97SetPlayVolume,
- set_record_volume: ac97SetRecordVolume,
- play_interrupt: ac97_play_isr,
- record_interrupt: ac97_rec_isr,
-};
+/**************************************************************************** + * + * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved. + * + * + * FILENAME + * w90n745_AC97.c + * + * VERSION + * 1.2 + * + * DESCRIPTION + * AC97 interface for W83972D codec + * + * DATA STRUCTURES + * None + * + * FUNCTIONS + * ... + * + * HISTORY + * 2004.06.01 Created by Yung-Chang Huang + * 2004.09.02 Ver 1.0 Modify for w90n745 coding standard + * 2005.11.24 Ver 1.1 Modified for uCLinux Sound Driver by PC34 QFu + * 2006.01.17 Ver 1.2 Modified for w90n745 Version B + * + * REMARK + * None + * + **************************************************************************/ +#include <linux/soundcard.h> +#include <linux/delay.h> +#include <asm/io.h> +#include <asm/irq.h> + +#include "w90n745_audio_regs.h" +#include "w90n745_audio.h" +#include "w90n745_ac97.h" + +//#define AC97_DEBUG +//#define AC97_DEBUG_ENTER_LEAVE +//#define AC97_DEBUG_MSG +//#define AC97_DEBUG_MSG2 + +#ifdef AC97_DEBUG +#define DBG(fmt, arg...) printk(fmt, ##arg) +#else +#define DBG(fmt, arg...) +#endif + +#ifdef AC97_DEBUG_ENTER_LEAVE +#define ENTER() DBG("[%-10s] : Enter\n", __FUNCTION__) +#define LEAVE() DBG("[%-10s] : Leave\n", __FUNCTION__) +#else +#define ENTER() +#define LEAVE() +#endif + +#ifdef AC97_DEBUG_MSG +#define MSG(fmt) DBG("[%-10s] : "fmt, __FUNCTION__) +#else +#define MSG(fmt) +#endif + +#ifdef AC97_DEBUG_MSG2 +#define MSG2(fmt, arg...) DBG("[%-10s] : "fmt, __FUNCTION__, ##arg) +#else +#define MSG2(fmt, arg...) +#endif + +#define AUDIO_WRITE(addr, val) writel(val, addr) +#define AUDIO_READ(addr) readl(addr) + +static AUDIO_T _tAC97; + +static int _bAC97Active = 0; +static volatile int _bPlayDmaToggle, _bRecDmaToggle; + +static void ac97StopPlay(void); + +struct semaphore ac97_sem; + +static unsigned int ac97_read_register(INT nIdx) +{ + volatile INT nWait; + unsigned int i; + + down(&ac97_sem); + + /* set the R_WB bit and write register index */ + AUDIO_WRITE(REG_ACTL_ACOS1, 0x80 | nIdx); + + /* set the valid frame bit and valid slots */ + AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) |0x11); + + udelay(100); + + /* polling the AC_R_FINISH */ + for (nWait = 0; nWait < 0x10000; nWait++) + { + if (AUDIO_READ(REG_ACTL_ACCON) & AC_R_FINISH) + break; + } + if (nWait == 0x10000) + MSG("ac97_read_register time out!\n"); + + AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) & ~1); + + if (AUDIO_READ(REG_ACTL_ACIS1) >> 2 != nIdx) + { MSG2("ac97_read_register - R_INDEX of REG_ACTL_ACIS1 not match!, 0x%x\n", AUDIO_READ(REG_ACTL_ACIS1)); } + + udelay(100); + i = AUDIO_READ(REG_ACTL_ACIS2) & 0xFFFF; + + up(&ac97_sem); + return (i); +} + + +static int ac97_write_register(INT nIdx, UINT16 sValue) +{ + volatile INT nWait; + + down(&ac97_sem); + + /* clear the R_WB bit and write register index */ + AUDIO_WRITE(REG_ACTL_ACOS1, nIdx); + + /* write register value */ + AUDIO_WRITE(REG_ACTL_ACOS2, (UINT32)sValue); + + /* set the valid frame bit and valid slots */ + AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) | 0x13); + + udelay(100); + + /* polling the AC_W_FINISH */ + for (nWait = 0; nWait < 0x10000; nWait++) + { + if (!(AUDIO_READ(REG_ACTL_ACCON) & AC_W_FINISH)) + break; + } + + AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) & ~3); + + up(&ac97_sem); + + + // paraniod? + //if (ac97_read_register(nIdx) != sValue) + // MSG2("ac97_write_register, nIdx=0x%x, mismatch, 0x%x must be 0x%x\n", nIdx, ac97_read_register(nIdx), sValue); + + return 0; +} + +#if 0 +static void ac97_read_all_registers() +{ + MSG("AC97_RESET = 0x%04x\n", ac97_read_register(AC97_RESET)); + MSG("AC97_MASTER_VOLUME = 0x%04x\n", ac97_read_register(AC97_MASTER_VOLUME)); + MSG("AC97_AUX_OUT_VOLUME = 0x%04x\n", ac97_read_register(AC97_AUX_OUT_VOLUME)); + MSG("AC97_MONO_VOLUME = 0x%04x\n", ac97_read_register(AC97_MONO_VOLUME)); + MSG("AC97_MASTER_TONE = 0x%04x\n", ac97_read_register(AC97_MASTER_TONE)); + MSG("AC97_PC_BEEP_VOLUME = 0x%04x\n", ac97_read_register(AC97_PC_BEEP_VOLUME)); + MSG("AC97_PHONE_VOLUME = 0x%04x\n", ac97_read_register(AC97_PHONE_VOLUME)); + MSG("AC97_MIC_VOLUME = 0x%04x\n", ac97_read_register(AC97_MIC_VOLUME)); + MSG("AC97_LINE_IN_VOLUME = 0x%04x\n", ac97_read_register(AC97_LINE_IN_VOLUME)); + MSG("AC97_CD_VOLUME = 0x%04x\n", ac97_read_register(AC97_CD_VOLUME)); + MSG("AC97_VIDEO_VOLUME = 0x%04x\n", ac97_read_register(AC97_VIDEO_VOLUME)); + MSG("AC97_AUX_IN_VOLUME = 0x%04x\n", ac97_read_register(AC97_AUX_IN_VOLUME)); + MSG("AC97_PCM_OUT_VOLUME = 0x%04x\n", ac97_read_register(AC97_PCM_OUT_VOLUME)); + MSG("AC97_RECORD_SELECT = 0x%04x\n", ac97_read_register(AC97_RECORD_SELECT)); + MSG("AC97_RECORD_GAIN = 0x%04x\n", ac97_read_register(AC97_RECORD_GAIN)); + MSG("AC97_RECORD_GAIN_MIC = 0x%04x\n", ac97_read_register(AC97_RECORD_GAIN_MIC)); + MSG("AC97_GENERAL_PURPOSE = 0x%04x\n", ac97_read_register(AC97_GENERAL_PURPOSE)); + MSG("AC97_3D_CONTROL = 0x%04x\n", ac97_read_register(AC97_3D_CONTROL)); + MSG("AC97_AUDIO_INT_PAGING = 0x%04x\n", ac97_read_register(AC97_AUDIO_INT_PAGING)); + MSG("AC97_POWERDOWN_CTRL = 0x%04x\n", ac97_read_register(AC97_POWERDOWN_CTRL)); + MSG("AC97_FRONT_DAC_RATE = 0x%04x\n", ac97_read_register(AC97_FRONT_DAC_RATE)); +} +#endif + +static void ac97_play_isr(void) +{ + int bPlayLastBlock; + + ENTER(); + + if(!(AUDIO_READ(REG_ACTL_CON) & T_DMA_IRQ)) + return; + + AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ(REG_ACTL_CON) | T_DMA_IRQ); + + if (_bPlayDmaToggle == 0) + { + if (AUDIO_READ(REG_ACTL_PSR) & P_DMA_MIDDLE_IRQ) + AUDIO_WRITE(REG_ACTL_PSR, P_DMA_MIDDLE_IRQ); + else + MSG("ac97_play_isr - miss middle!\n"); + + _bPlayDmaToggle = 1; + + bPlayLastBlock = _tAC97.fnPlayCallBack(_tAC97.uPlayBufferAddr, + _tAC97.uPlayBufferLength/2); + } + else + { + if (AUDIO_READ(REG_ACTL_PSR) & P_DMA_END_IRQ) + AUDIO_WRITE(REG_ACTL_PSR, P_DMA_END_IRQ); + else + MSG("ac97_play_isr - miss end!\n"); + + _bPlayDmaToggle = 0; + + bPlayLastBlock = _tAC97.fnPlayCallBack(_tAC97.uPlayBufferAddr+ _tAC97.uPlayBufferLength/ 2, + _tAC97.uPlayBufferLength/2); + } + + + /* here, we will check whether the next buffer is ready. If not, stop play. */ + if (bPlayLastBlock) + AUDIO_WRITE(REG_ACTL_PSR, P_DMA_MIDDLE_IRQ | P_DMA_END_IRQ); + + + LEAVE(); + +} + + +static void ac97_rec_isr(void) +{ + int bPlayLastBlock; + + ENTER(); + + if(!(AUDIO_READ(REG_ACTL_CON) & R_DMA_IRQ)) + return; + + AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ(REG_ACTL_CON) | R_DMA_IRQ); + + if (_bRecDmaToggle == 0) + { + if (AUDIO_READ(REG_ACTL_RSR) & R_DMA_MIDDLE_IRQ) + AUDIO_WRITE(REG_ACTL_RSR, R_DMA_MIDDLE_IRQ); + else + MSG("ac97_rec_isr - miss middle!\n"); + + _bRecDmaToggle = 1; + bPlayLastBlock = _tAC97.fnRecCallBack(_tAC97.uRecordBufferAddr, + _tAC97.uRecordBufferLength/2); + } + else + { + if (AUDIO_READ(REG_ACTL_RSR) & R_DMA_END_IRQ) + AUDIO_WRITE(REG_ACTL_RSR, R_DMA_END_IRQ); + else + MSG("ac97_rec_isr - miss end!\n"); + + _bRecDmaToggle = 0; + bPlayLastBlock = _tAC97.fnRecCallBack(_tAC97.uRecordBufferAddr + _tAC97.uRecordBufferLength / 2, + _tAC97.uRecordBufferLength /2); + } + + if (bPlayLastBlock) + AUDIO_WRITE(REG_ACTL_RSR, R_DMA_MIDDLE_IRQ | R_DMA_END_IRQ); + + LEAVE(); +} + +static int ac97_reset(void) +{ + ENTER(); + + AUDIO_WRITE(REG_CLKSEL, AUDIO_READ(REG_CLKSEL) | 0x10000); + + AUDIO_WRITE(0xFFF83000,0x155);//GPIO_CFG0 PT0CFG0~4 + AUDIO_WRITE(0xFFF83004,0xd);//GPIO4,1:In GPIO0,2,3:Out + + //AUDIO_WRITE(REG_GPIOA_OE, (AUDIO_READ(REG_GPIOA_OE) & 0xFFFFC0FF) | 0x2700); + + /* disable pull-high/low */ + //AUDIO_WRITE(REG_GPIOA_PE, 0x3F00); + + udelay(1000); + + _tAC97.sPlayVolume = 0x0000; + _tAC97.sRecVolume = 0x0000; + + /* enable audio controller and AC-link interface */ + AUDIO_WRITE(REG_ACTL_CON, IIS_AC_PIN_SEL | AUDIO_EN | ACLINK_EN | PFIFO_EN | RFIFO_EN | T_DMA_IRQ | R_DMA_IRQ | DMA_EN); + udelay(1000); + + /* reset Audio Controller */ + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | ACTL_RESET_BIT); + udelay(1000); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~ACTL_RESET_BIT); + udelay(1000); + + /* reset AC-link interface */ + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | AC_RESET); + udelay(1000); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~AC_RESET); + udelay(1000); + + + /* cold reset AC 97 */ + AUDIO_WRITE(REG_ACTL_ACCON, AUDIO_READ(REG_ACTL_ACCON) | AC_C_RES); + udelay(1000); + AUDIO_WRITE(REG_ACTL_ACCON, AUDIO_READ(REG_ACTL_ACCON) & ~AC_C_RES); + udelay(1000); + + + if (!(AUDIO_READ(REG_ACTL_ACIS0) & 0x10)) + { + MSG("Error - AC97 codec ready was not set, cold reset failed!\n"); + return ERR_AC97_CODEC_RESET; + } + + udelay(100); + //ac97_read_all_registers(); + + /* set volumes */ + + ac97_write_register(AC97_MASTER_VOLUME, _tAC97.sPlayVolume); + + ac97_write_register(AC97_MONO_VOLUME, 0x000f); + //ac97_write_register(AC97_MASTER_TONE, 0x0303); + ac97_write_register(AC97_MIC_VOLUME, 0x8000); + //ac97_write_register(AC97_LINE_IN_VOLUME, 0x0707); + //ac97_write_register(AC97_AUX_IN_VOLUME, 0x0707); + ac97_write_register(AC97_PCM_OUT_VOLUME, _tAC97.sPlayVolume); + + ac97_write_register(AC97_RECORD_SELECT, 0); /* record select MIC in */ + ac97_write_register(AC97_RECORD_GAIN, 0x0404); + ac97_write_register(AC97_RECORD_GAIN_MIC, 0x0004); + ac97_write_register(AC97_GENERAL_PURPOSE, 0); + + LEAVE(); + + return 0; +} + +static VOID ac97SetPlaySampleRate(INT nSamplingRate) +{ + ENTER(); + + /* set play sampling rate */ + if (nSamplingRate != 48000) + { + /* enable VRA and set sampling frequency */ + ac97_write_register(AC97_EXT_AUDIO_CTRL, ac97_read_register(AC97_EXT_AUDIO_CTRL)|0x1); + ac97_write_register(AC97_FRONT_DAC_RATE, nSamplingRate); + } + + _tAC97.nPlaySamplingRate = nSamplingRate; + + LEAVE(); +} + +static VOID ac97SetRecordSampleRate(INT nSamplingRate) +{ + ENTER(); + + /* set record sampling rate */ + if (nSamplingRate != 48000) + { + /* enable VRA and set sampling frequency */ + ac97_write_register(AC97_EXT_AUDIO_CTRL, ac97_read_register(AC97_EXT_AUDIO_CTRL)|0x1); + ac97_write_register(AC97_LR_ADC_RATE, nSamplingRate); + } + + _tAC97.nRecSamplingRate = nSamplingRate; + + LEAVE(); +} + +static VOID ac97SetPlayCallBackFunction(AU_CB_FUN_T fnCallBack) +{ + ENTER(); + + _tAC97.fnPlayCallBack = fnCallBack; + + LEAVE(); +} + +static VOID ac97SetRecordCallBackFunction(AU_CB_FUN_T fnCallBack) +{ + ENTER(); + + _tAC97.fnRecCallBack = fnCallBack; + + LEAVE(); +} + + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* ac97SetPlayVolume */ +/* */ +/* DESCRIPTION */ +/* Set AC97 left and right channel play volume. */ +/* */ +/* INPUTS */ +/* ucLeftVol play volume of left channel */ +/* ucRightVol play volume of left channel */ +/* 0: mute */ +/* 1: minimal volume */ +/* 31: maxmum volume */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static int ac97SetPlayVolume(UINT32 ucLeftVol, UINT32 ucRightVol) +{ + int nLData, nRData; + + ENTER(); + + //MSG2("Set AC97 volume to : %d-%d\n", ucLeftVol, ucRightVol); + + if (ucLeftVol == 0) + nLData = 0x80; + else + nLData = 31 - (ucLeftVol & 0x1f); + + if (ucRightVol == 0) + nRData = 0x80; + else + nRData = 31 - (ucRightVol & 0x1f); + + _tAC97.sPlayVolume = (nLData << 8) | nRData; + ac97_write_register(AC97_PCM_OUT_VOLUME, (nLData << 8) | nRData); + //ac97_write_register(AC97_PCM_OUT_VOLUME, 0x101); + + if (ucLeftVol == 0) + nLData = 0x80; + else + nLData = 62 - ucLeftVol*2; + + if (ucRightVol == 0) + nRData = 0x80; + else + nRData = 62 - ucRightVol*2; + + ac97_write_register(AC97_AUX_OUT_VOLUME, (nLData << 8) | nRData); + ac97_write_register(AC97_MASTER_VOLUME, (nLData << 8) | nRData); + + MSG2("AC97_MASTER_VOLUME = 0x%04x\r\n", ac97_read_register(AC97_MASTER_VOLUME)); + MSG2("AC97_AUX_OUT_VOLUME = 0x%04x\r\n", ac97_read_register(AC97_AUX_OUT_VOLUME)); + MSG2("AC97_PCM_OUT_VOLUME = 0x%04x\r\n", ac97_read_register(AC97_PCM_OUT_VOLUME)); +#if 0 + down(&ac97_sem); + if (_bAC97Active & AC97_PLAY_ACTIVE) + AUDIO_WRITE(REG_ACTL_ACOS0, 0x1f); + else + AUDIO_WRITE(REG_ACTL_ACOS0, 0); + up(&ac97_sem); +#endif + LEAVE(); + + return 0; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* ac97SetRecordVolume */ +/* */ +/* DESCRIPTION */ +/* Set AC97 left and right channel record volume. */ +/* */ +/* INPUTS */ +/* ucLeftVol record volume of left channel */ +/* ucRightVol record volume of left channel */ +/* 0: mute */ +/* 1: minimal volume */ +/* 31: maxmum volume */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static int ac97SetRecordVolume(UINT32 ucLeftVol, UINT32 ucRightVol) +{ + //INT nStatus; + + ENTER(); + + if (ucLeftVol == 0) + ucLeftVol = 0x80; + else + ucLeftVol = 32 - (ucLeftVol & 0x1f); + + if (ucRightVol == 0) + ucRightVol = 0x80; + else + ucRightVol = 32 - (ucRightVol & 0x1f); + + _tAC97.sRecVolume = (ucLeftVol << 8) | ucRightVol; + + ac97_write_register(AC97_MIC_VOLUME, ucRightVol ); + + //ac97_read_all_registers(); + LEAVE(); + + return 0; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* ac97StartPlay */ +/* */ +/* DESCRIPTION */ +/* Start AC97 playback. */ +/* */ +/* INPUTS */ +/* fnCallBack client program provided callback function. The audio */ +/* driver will call back to get next block of PCM data */ +/* nSamplingRate the playback sampling rate. Supported sampling */ +/* rate are 48000, 44100, 32000, 24000, 22050, 16000, */ +/* 11025, and 8000 Hz */ +/* nChannels number of playback nChannels */ +/* 1: single channel, otherwise: double nChannels */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static int ac97StartPlay(AU_CB_FUN_T fnCallBack, INT nSamplingRate, INT nChannels) +{ + INT nStatus; + + ENTER(); + + if (_bAC97Active & AC97_PLAY_ACTIVE) + return ERR_AC97_PLAY_ACTIVE; /* AC97 was playing */ + + + if (_bAC97Active == 0) + { + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~PLAY_LEFT_CHNNEL &~PLAY_RIGHT_CHNNEL); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | PLAY_RIGHT_CHNNEL); + if (nChannels != 1) + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | PLAY_LEFT_CHNNEL); + + nStatus = ac97_reset(); + if (nStatus < 0) + return nStatus; + } + + /* disable by Qfu , for the installation of irq has been done in wb_audio.c + the only thing to do is to enable irq by this routine */ + Enable_Int(AU_PLAY_INT_NUM); + + /* set play sampling rate */ + ac97SetPlaySampleRate(nSamplingRate); + ac97SetPlayCallBackFunction(fnCallBack); + + /* set DMA play destination base address */ + AUDIO_WRITE(REG_ACTL_PDSTB, _tAC97.uPlayBufferAddr); + + /* set DMA play buffer length */ + AUDIO_WRITE(REG_ACTL_PDST_LENGTH, _tAC97.uPlayBufferLength); + + /* start playing */ + MSG("AC97 start playing...\n"); + _bPlayDmaToggle = 0; + down(&ac97_sem); + AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) | 0x1C); + up(&ac97_sem); + AUDIO_WRITE(REG_ACTL_PSR, 0x3); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | AC_PLAY); + _bAC97Active |= AC97_PLAY_ACTIVE; + + LEAVE(); + + return 0; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* ac97StopPlay */ +/* */ +/* DESCRIPTION */ +/* Stop AC97 playback immdediately. */ +/* */ +/* INPUTS */ +/* None */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static void ac97StopPlay(void) +{ + ENTER(); + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(PLAY_RIGHT_CHNNEL | PLAY_LEFT_CHNNEL)); + + if (!(_bAC97Active & AC97_PLAY_ACTIVE)) + return; + + + //ac97_read_all_registers (); + + /* stop playing */ + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~AC_PLAY); + + down(&ac97_sem); + AUDIO_WRITE(REG_ACTL_ACOS0, AUDIO_READ(REG_ACTL_ACOS0) & ~0xC); + up(&ac97_sem); + + + _bAC97Active &= ~AC97_PLAY_ACTIVE; + /* disable audio play interrupt */ + if (!_bAC97Active) + Disable_Int(AU_PLAY_INT_NUM); + + + LEAVE(); + + return; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* ac97StartRecord */ +/* */ +/* DESCRIPTION */ +/* Start AC97 record. */ +/* */ +/* INPUTS */ +/* fnCallBack client program provided callback function. The audio */ +/* driver will call back to deliver the newly recorded */ +/* block of PCM data */ +/* nSamplingRate the record sampling rate. Supported sampling */ +/* rate are 48000, 44100, 32000, 24000, 22050, 16000, */ +/* 11025, and 8000 Hz */ +/* nChannels number of record nChannels */ +/* 1: single channel, otherwise: double nChannels */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static int ac97StartRecord(AU_CB_FUN_T fnCallBack, INT nSamplingRate, INT nChannels) +{ + INT nStatus; + unsigned int i; + + ENTER(); + + if (_bAC97Active & AC97_REC_ACTIVE) + return ERR_AC97_REC_ACTIVE; /* AC97 was recording */ + + if (_bAC97Active == 0) + { + + nStatus = ac97_reset(); + if (nStatus < 0) + return nStatus; + } + + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~RECORD_RIGHT_CHNNEL &~RECORD_LEFT_CHNNEL); + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | RECORD_RIGHT_CHNNEL); + if (nChannels != 1) { + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | RECORD_LEFT_CHNNEL); + } + + + + + /* enable AC97 record interrupt */ + Enable_Int(AU_REC_INT_NUM); + + + + /* set record sampling rate */ + ac97SetRecordSampleRate(nSamplingRate); + ac97SetRecordCallBackFunction(fnCallBack); + + + /* set DMA record destination base address */ + AUDIO_WRITE(REG_ACTL_RDSTB, _tAC97.uRecordBufferAddr); + + /* set DMA record buffer length */ + AUDIO_WRITE(REG_ACTL_RDST_LENGTH, _tAC97.uRecordBufferLength); + + /* start recording */ + MSG("AC97 start recording...\n"); + _bRecDmaToggle = 0; + AUDIO_WRITE(REG_ACTL_RSR, 0x3); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | AC_RECORD); + _bAC97Active |= AC97_REC_ACTIVE; + + LEAVE(); + + return 0; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* ac97StopRecord */ +/* */ +/* DESCRIPTION */ +/* Stop AC97 record immediately. */ +/* */ +/* INPUTS */ +/* None */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static void ac97StopRecord(void) +{ + ENTER(); + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(RECORD_RIGHT_CHNNEL | RECORD_LEFT_CHNNEL)); + + if (!(_bAC97Active & AC97_REC_ACTIVE)) + return; + + //ac97_read_all_registers (); + /* stop recording */ + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~AC_RECORD); + + _bAC97Active &= ~AC97_REC_ACTIVE; + /* disable audio record interrupt */ + if (!_bAC97Active) + Disable_Int(AU_PLAY_INT_NUM); + + + LEAVE(); + + return; +} + +static void ac97SetPlayBuffer(UINT32 uDMABufferAddr, UINT32 uDMABufferLength) +{ + ENTER(); + + _tAC97.uPlayBufferAddr = uDMABufferAddr; + _tAC97.uPlayBufferLength = uDMABufferLength; + + LEAVE(); +} + +static void ac97SetRecordBuffer(UINT32 uDMABufferAddr, UINT32 uDMABufferLength) +{ + ENTER(); + + _tAC97.uRecordBufferAddr = uDMABufferAddr; + _tAC97.uRecordBufferLength = uDMABufferLength; + + LEAVE(); +} + + +static INT ac97Init(VOID) +{ + int nStatus = 0; + + ENTER(); + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~PLAY_LEFT_CHNNEL &~PLAY_RIGHT_CHNNEL); + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~RECORD_LEFT_CHNNEL &~RECORD_RIGHT_CHNNEL); + + nStatus = ac97_reset(); + if (nStatus < 0) + return nStatus; + + LEAVE(); + + return 0; +} + +static INT ac97GetCapacity(VOID) +{ + return DSP_CAP_DUPLEX; /* support full duplex */ +} + +WB_AUDIO_CODEC_T wb_ac97_codec = { + dev: AU_DEV_AC97, + get_capacity: ac97GetCapacity, + set_play_buffer: ac97SetPlayBuffer, + set_record_buffer: ac97SetRecordBuffer, + reset: ac97Init, + start_play: ac97StartPlay, + stop_play: ac97StopPlay, + start_record: ac97StartRecord, + stop_record: ac97StopRecord, + set_play_volume: ac97SetPlayVolume, + set_record_volume: ac97SetRecordVolume, + play_interrupt: ac97_play_isr, + record_interrupt: ac97_rec_isr, +}; diff --git a/uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.h b/uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.h index 96c4dc4..8919160 100644 --- a/uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.h +++ b/uClinux-2.4.20-uc1/drivers/sound/w90n745_ac97.h @@ -1,60 +1,60 @@ -/**************************************************************************************************
- *
- * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved.
- *
- * FILENAME
- * w90n745_AC97.h
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * This file contains the register map of AC97 audio codec
- *
- * HISTORY
- * 02/09/2004 Ver 1.0 Created by PC30 YCHuang
- *
- * REMARK
- * None
- *
- *************************************************************************************************/
-#ifndef _W90N745_AC97_H_
-#define _W90N745_AC97_H_
-
-#define AC97_RESET 0x00
-#define AC97_MASTER_VOLUME 0x02
-#define AC97_AUX_OUT_VOLUME 0x04
-#define AC97_MONO_VOLUME 0x06
-#define AC97_MASTER_TONE 0x08
-#define AC97_PC_BEEP_VOLUME 0x0A
-#define AC97_PHONE_VOLUME 0x0C
-#define AC97_MIC_VOLUME 0x0E
-#define AC97_LINE_IN_VOLUME 0x10
-#define AC97_CD_VOLUME 0x12
-#define AC97_VIDEO_VOLUME 0x14
-#define AC97_AUX_IN_VOLUME 0x16
-#define AC97_PCM_OUT_VOLUME 0x18
-#define AC97_RECORD_SELECT 0x1A
-#define AC97_RECORD_GAIN 0x1C
-#define AC97_RECORD_GAIN_MIC 0x1E
-#define AC97_GENERAL_PURPOSE 0x20
-#define AC97_3D_CONTROL 0x22
-#define AC97_AUDIO_INT_PAGING 0x24
-#define AC97_POWERDOWN_CTRL 0x26
-#define AC97_EXT_AUDIO_ID 0x28
-#define AC97_EXT_AUDIO_CTRL 0x2A
-#define AC97_FRONT_DAC_RATE 0x2C
-#define AC97_LR_ADC_RATE 0x32
-#define AC97_MIC_ADC_RATE 0x34
-
-/* bit definition of ATCL_CON register */
-#define AUDCLK_EN 0x8000
-#define PFIFO_EN 0x4000
-#define RFIFO_EN 0x2000
-
-#define AC97_ACTIVE 0x1
-#define AC97_PLAY_ACTIVE 0x2
-#define AC97_REC_ACTIVE 0x4
-
-
-#endif /* _W90N745_AC97_H_ */
+/************************************************************************************************** + * + * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved. + * + * FILENAME + * w90n745_AC97.h + * + * VERSION + * 1.0 + * + * DESCRIPTION + * This file contains the register map of AC97 audio codec + * + * HISTORY + * 02/09/2004 Ver 1.0 Created by PC30 YCHuang + * + * REMARK + * None + * + *************************************************************************************************/ +#ifndef _W90N745_AC97_H_ +#define _W90N745_AC97_H_ + +#define AC97_RESET 0x00 +#define AC97_MASTER_VOLUME 0x02 +#define AC97_AUX_OUT_VOLUME 0x04 +#define AC97_MONO_VOLUME 0x06 +#define AC97_MASTER_TONE 0x08 +#define AC97_PC_BEEP_VOLUME 0x0A +#define AC97_PHONE_VOLUME 0x0C +#define AC97_MIC_VOLUME 0x0E +#define AC97_LINE_IN_VOLUME 0x10 +#define AC97_CD_VOLUME 0x12 +#define AC97_VIDEO_VOLUME 0x14 +#define AC97_AUX_IN_VOLUME 0x16 +#define AC97_PCM_OUT_VOLUME 0x18 +#define AC97_RECORD_SELECT 0x1A +#define AC97_RECORD_GAIN 0x1C +#define AC97_RECORD_GAIN_MIC 0x1E +#define AC97_GENERAL_PURPOSE 0x20 +#define AC97_3D_CONTROL 0x22 +#define AC97_AUDIO_INT_PAGING 0x24 +#define AC97_POWERDOWN_CTRL 0x26 +#define AC97_EXT_AUDIO_ID 0x28 +#define AC97_EXT_AUDIO_CTRL 0x2A +#define AC97_FRONT_DAC_RATE 0x2C +#define AC97_LR_ADC_RATE 0x32 +#define AC97_MIC_ADC_RATE 0x34 + +/* bit definition of ATCL_CON register */ +#define AUDCLK_EN 0x8000 +#define PFIFO_EN 0x4000 +#define RFIFO_EN 0x2000 + +#define AC97_ACTIVE 0x1 +#define AC97_PLAY_ACTIVE 0x2 +#define AC97_REC_ACTIVE 0x4 + + +#endif /* _W90N745_AC97_H_ */ diff --git a/uClinux-2.4.20-uc1/drivers/sound/w90n745_audio.h b/uClinux-2.4.20-uc1/drivers/sound/w90n745_audio.h index 421f3d4..665143e 100644 --- a/uClinux-2.4.20-uc1/drivers/sound/w90n745_audio.h +++ b/uClinux-2.4.20-uc1/drivers/sound/w90n745_audio.h @@ -1,145 +1,145 @@ -/**************************************************************************************************
- *
- * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved.
- *
- * FILENAME
- * W90N745_AUDIO.H
- *
- * VERSION
- * 1.1
- *
- * DESCRIPTION
- * This file contains the main structure of w90n745 audio module
- *
- * HISTORY
- * 02/09/2004 Ver 1.0 Created by PC30 YCHuang
- * 11/25/2005 Ver 1.1 Modified by PC34 QFu
- *
- * REMARK
- * None
- *
- *************************************************************************************************/
-
-#ifndef _W90N745_AUDIO_H_
-#define _W90N745_AUDIO_H_
-
-#include <asm/arch/cdefs.h>
-#include <asm/semaphore.h>
-
-typedef int (*AU_CB_FUN_T)(UINT32, UINT32);
-
-typedef enum au_dev_e
-{
- AU_DEV_AC97,
- AU_DEV_IIS
-} AU_DEV_E;
-
-typedef struct wb_audio_codec_t{
- AU_DEV_E dev; /* codec type */
- INT (*get_capacity)(VOID);
- VOID (*set_play_buffer)(UINT32, UINT32);
- VOID (*set_record_buffer)(UINT32, UINT32);
-
- INT (*set_play_volume)(UINT32 nLeft, UINT32 nRight);
- INT (*set_record_volume)(UINT32 nLeft, UINT32 nRight);
-
- INT (*reset)(VOID);
-
- INT (*start_play)(AU_CB_FUN_T fnCallBack, INT nSamplingRate, INT nChannels);
- VOID (*stop_play)(VOID);
-
- INT (*start_record)(AU_CB_FUN_T fnCallBack, INT nSamplingRate, INT nChannels);
- VOID (*stop_record)(VOID);
-
- VOID (*play_interrupt)(VOID); /* nonzero play stopped */
- VOID (*record_interrupt)(VOID);
-}WB_AUDIO_CODEC_T;
-
-typedef struct audio_t
-{
- AU_CB_FUN_T fnPlayCallBack;
- AU_CB_FUN_T fnRecCallBack;
- INT nPlaySamplingRate;
- INT nRecSamplingRate;
- short sPlayVolume;
- short sRecVolume;
- UINT32 uPlayBufferAddr;
- UINT32 uPlayBufferLength;
- UINT32 uRecordBufferAddr;
- UINT32 uRecordBufferLength;
-}AUDIO_T;
-
-typedef struct wb_audio_t{
- int state;
- int open_flags;
- int dsp_dev, dsp_openflag;
- int mixer_dev, mixer_openflag;
- unsigned int play_buf_addr, record_buf_addr;
- unsigned int play_buf_length, record_buf_length;
- int nSamplingRate;
- int nChannels;
- int nPlayVolumeLeft, nPlayVolumeRight, nRecordVolumeLeft, nRecordVolumeRight;
-
- struct{
- int ptr;
- }play_half_buf[2], record_half_buf[2];
-
- WB_AUDIO_CODEC_T *codec;
- struct semaphore dsp_read_sem, dsp_write_sem, mixer_sem;
- struct fasync_struct *fasync_ptr;
- wait_queue_head_t write_wait_queue, read_wait_queue;
-}WB_AUDIO_T;
-
-
-
-#define AU_SAMPLE_RATE_48000 48000
-#define AU_SAMPLE_RATE_44100 44100
-#define AU_SAMPLE_RATE_32000 32000
-#define AU_SAMPLE_RATE_24000 24000
-#define AU_SAMPLE_RATE_22050 22050
-#define AU_SAMPLE_RATE_16000 16000
-#define AU_SAMPLE_RATE_11025 11025
-#define AU_SAMPLE_RATE_8000 8000
-
-#define AU_CH_MONO 1
-#define AU_CH_STEREO 2
-
-/* state code */
-#define AU_STATE_NOP 0
-#define AU_STATE_PLAYING 1
-#define AU_STATE_RECORDING 2
-
-/* capacity */
-#define AU_CAP_DUPLEX 1
-
-/* Error Code */
-#define ERR_AU_GENERAL_ERROR -1
-#define ERR_AU_NO_MEMORY -5 /* memory allocate failure */
-#define ERR_AU_ILL_BUFF_SIZE -10 /* illegal callback buffer size */
-#define ERR_AC97_CODEC_RESET -20 /* AC97 codec reset failed */
-#define ERR_AC97_PLAY_ACTIVE -22 /* AC97 playback has been activated */
-#define ERR_AC97_REC_ACTIVE -23 /* AC97 record has been activated */
-#define ERR_AC97_NO_DEVICE -24 /* have no AC97 codec on board */
-#define ERR_MA3_PLAY_ACTIVE -50 /* MA3 playback has been activated */
-#define ERR_MA3_NO_DEVICE -51 /* have no MA3 chip on board */
-#define ERR_MA5_PLAY_ACTIVE -80 /* MA5 playback has been activated */
-#define ERR_MA5_NO_DEVICE -81 /* have no MA5 chip on board */
-#define ERR_MA5I_NO_DEVICE -90 /* have no MA5i chip on board */
-#define ERR_DAC_PLAY_ACTIVE -110 /* DAC playback has been activated */
-#define ERR_DAC_NO_DEVICE -111 /* DAC is not available */
-#define ERR_ADC_REC_ACTIVE -120 /* ADC record has been activated */
-#define ERR_ADC_NO_DEVICE -121 /* ADC is not available */
-#define ERR_IIS_PLAY_ACTIVE -140 /* IIS playback has been activated */
-#define ERR_IIS_REC_ACTIVE -141 /* IIS record has been activated */
-#define ERR_IIS_NO_DEVICE -142 /* has no IIS codec on board */
-#define ERR_WM8753_NO_DEVICE -150 /* has no wm8753 codec on board */
-#define ERR_W5691_PLAY_ACTIVE -160 /* W5691 playback has been activated */
-#define ERR_W5691_NO_DEVICE -161 /* Have no W5691 chip on board */
-
-#define ERR_NO_DEVICE -201 /* audio device not available */
-
-extern WB_AUDIO_CODEC_T wb_ac97_codec;
-extern WB_AUDIO_CODEC_T wb_i2s_codec;
-
-#endif /* _W90N745_AUDIO_H_ */
-
+/************************************************************************************************** + * + * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved. + * + * FILENAME + * W90N745_AUDIO.H + * + * VERSION + * 1.1 + * + * DESCRIPTION + * This file contains the main structure of w90n745 audio module + * + * HISTORY + * 02/09/2004 Ver 1.0 Created by PC30 YCHuang + * 11/25/2005 Ver 1.1 Modified by PC34 QFu + * + * REMARK + * None + * + *************************************************************************************************/ + +#ifndef _W90N745_AUDIO_H_ +#define _W90N745_AUDIO_H_ + +#include <asm/arch/cdefs.h> +#include <asm/semaphore.h> + +typedef int (*AU_CB_FUN_T)(UINT32, UINT32); + +typedef enum au_dev_e +{ + AU_DEV_AC97, + AU_DEV_IIS +} AU_DEV_E; + +typedef struct wb_audio_codec_t{ + AU_DEV_E dev; /* codec type */ + INT (*get_capacity)(VOID); + VOID (*set_play_buffer)(UINT32, UINT32); + VOID (*set_record_buffer)(UINT32, UINT32); + + INT (*set_play_volume)(UINT32 nLeft, UINT32 nRight); + INT (*set_record_volume)(UINT32 nLeft, UINT32 nRight); + + INT (*reset)(VOID); + + INT (*start_play)(AU_CB_FUN_T fnCallBack, INT nSamplingRate, INT nChannels); + VOID (*stop_play)(VOID); + + INT (*start_record)(AU_CB_FUN_T fnCallBack, INT nSamplingRate, INT nChannels); + VOID (*stop_record)(VOID); + + VOID (*play_interrupt)(VOID); /* nonzero play stopped */ + VOID (*record_interrupt)(VOID); +}WB_AUDIO_CODEC_T; + +typedef struct audio_t +{ + AU_CB_FUN_T fnPlayCallBack; + AU_CB_FUN_T fnRecCallBack; + INT nPlaySamplingRate; + INT nRecSamplingRate; + short sPlayVolume; + short sRecVolume; + UINT32 uPlayBufferAddr; + UINT32 uPlayBufferLength; + UINT32 uRecordBufferAddr; + UINT32 uRecordBufferLength; +}AUDIO_T; + +typedef struct wb_audio_t{ + int state; + int open_flags; + int dsp_dev, dsp_openflag; + int mixer_dev, mixer_openflag; + unsigned int play_buf_addr, record_buf_addr; + unsigned int play_buf_length, record_buf_length; + int nSamplingRate; + int nChannels; + int nPlayVolumeLeft, nPlayVolumeRight, nRecordVolumeLeft, nRecordVolumeRight; + + struct{ + int ptr; + }play_half_buf[2], record_half_buf[2]; + + WB_AUDIO_CODEC_T *codec; + struct semaphore dsp_read_sem, dsp_write_sem, mixer_sem; + struct fasync_struct *fasync_ptr; + wait_queue_head_t write_wait_queue, read_wait_queue; +}WB_AUDIO_T; + + + +#define AU_SAMPLE_RATE_48000 48000 +#define AU_SAMPLE_RATE_44100 44100 +#define AU_SAMPLE_RATE_32000 32000 +#define AU_SAMPLE_RATE_24000 24000 +#define AU_SAMPLE_RATE_22050 22050 +#define AU_SAMPLE_RATE_16000 16000 +#define AU_SAMPLE_RATE_11025 11025 +#define AU_SAMPLE_RATE_8000 8000 + +#define AU_CH_MONO 1 +#define AU_CH_STEREO 2 + +/* state code */ +#define AU_STATE_NOP 0 +#define AU_STATE_PLAYING 1 +#define AU_STATE_RECORDING 2 + +/* capacity */ +#define AU_CAP_DUPLEX 1 + +/* Error Code */ +#define ERR_AU_GENERAL_ERROR -1 +#define ERR_AU_NO_MEMORY -5 /* memory allocate failure */ +#define ERR_AU_ILL_BUFF_SIZE -10 /* illegal callback buffer size */ +#define ERR_AC97_CODEC_RESET -20 /* AC97 codec reset failed */ +#define ERR_AC97_PLAY_ACTIVE -22 /* AC97 playback has been activated */ +#define ERR_AC97_REC_ACTIVE -23 /* AC97 record has been activated */ +#define ERR_AC97_NO_DEVICE -24 /* have no AC97 codec on board */ +#define ERR_MA3_PLAY_ACTIVE -50 /* MA3 playback has been activated */ +#define ERR_MA3_NO_DEVICE -51 /* have no MA3 chip on board */ +#define ERR_MA5_PLAY_ACTIVE -80 /* MA5 playback has been activated */ +#define ERR_MA5_NO_DEVICE -81 /* have no MA5 chip on board */ +#define ERR_MA5I_NO_DEVICE -90 /* have no MA5i chip on board */ +#define ERR_DAC_PLAY_ACTIVE -110 /* DAC playback has been activated */ +#define ERR_DAC_NO_DEVICE -111 /* DAC is not available */ +#define ERR_ADC_REC_ACTIVE -120 /* ADC record has been activated */ +#define ERR_ADC_NO_DEVICE -121 /* ADC is not available */ +#define ERR_IIS_PLAY_ACTIVE -140 /* IIS playback has been activated */ +#define ERR_IIS_REC_ACTIVE -141 /* IIS record has been activated */ +#define ERR_IIS_NO_DEVICE -142 /* has no IIS codec on board */ +#define ERR_WM8753_NO_DEVICE -150 /* has no wm8753 codec on board */ +#define ERR_W5691_PLAY_ACTIVE -160 /* W5691 playback has been activated */ +#define ERR_W5691_NO_DEVICE -161 /* Have no W5691 chip on board */ + +#define ERR_NO_DEVICE -201 /* audio device not available */ + +extern WB_AUDIO_CODEC_T wb_ac97_codec; +extern WB_AUDIO_CODEC_T wb_i2s_codec; + +#endif /* _W90N745_AUDIO_H_ */ + diff --git a/uClinux-2.4.20-uc1/drivers/sound/w90n745_audio_regs.h b/uClinux-2.4.20-uc1/drivers/sound/w90n745_audio_regs.h index abcfb64..d173c4c 100644 --- a/uClinux-2.4.20-uc1/drivers/sound/w90n745_audio_regs.h +++ b/uClinux-2.4.20-uc1/drivers/sound/w90n745_audio_regs.h @@ -1,199 +1,199 @@ -/**************************************************************************************************
- *
- * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved.
- *
- * FILENAME
- * w90n745_Audio_REGS.H
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * This file contains the register map of W90N710 audio controller.
- *
- * HISTORY
- * 05/26/2004 Ver 1.0 Created by PC30 YCHuang
- * 11/24/2005 Ver 1.1 Modified by PC34 QFu
- *
- * REMARK
- * None
- *
- *************************************************************************************************/
-#ifndef _W90N745_AUDIO_REGS_H_
-#define _W90N745_AUDIO_REGS_H_
-
-#define REG_CLKSEL 0xfff0000c
-
-#define GPIO_BA 0xFFF83000
-/**********************************************************************************************************
- *
- * 4. GPIO Control Registers
- *
- **********************************************************************************************************/
-/* GPIO Pins */
-#define REG_GPIO_CFG (GPIO_BA+0x00) /* GPIO Pins Output Enable Control Register */
-#define REG_GPIO_DIR (GPIO_BA+0x04) /* GPIO Pins Data Register */
-#define REG_GPIO_DATAOUT (GPIO_BA+0x08) /* GPIO Pins Status Register */
-
-
-/* GPIO-A Pins */
-#define REG_GPIOA_OE (GPIO_BA+0x20) /* GPIO-A Pins Output Enable Control Register */
-#define REG_GPIOA_DAT (GPIO_BA+0x24) /* GPIO-A Pins Data Register */
-#define REG_GPIOA_STS (GPIO_BA+0x28) /* GPIO-A Pins Status Register */
-#define REG_GPIOA_PE (GPIO_BA+0x2c) /* GPIO-A Pull-Up/Down Enable Control Register */
-
-/* GPIO-B Pins */
-#define REG_GPIOB_OE (GPIO_BA+0x30) /* GPIO-B Pins Output Enable Control Register */
-#define REG_GPIOB_DAT (GPIO_BA+0x34) /* GPIO-B Pins Data Register */
-#define REG_GPIOB_STS (GPIO_BA+0x38) /* GPIO-B Pins Status Register */
-#define REG_GPIOB_PE (GPIO_BA+0x3c) /* GPIO-B Pull-Up/Down Enable Control Register */
-
-/* GPIO-S Pins */
-#define REG_GPIOS_OE (GPIO_BA+0x40) /* GPIO-S Pins Output Enable Control Register */
-#define REG_GPIOS_DAT (GPIO_BA+0x44) /* GPIO-S Pins Data Register */
-#define REG_GPIOS_STS (GPIO_BA+0x48) /* GPIO-S Pins Status Register */
-#define REG_GPIOS_PE (GPIO_BA+0x4c) /* GPIO-S Pull-Up/Down Enable Control Register */
-
-
-/* to be modified in future */
-//#include "w90n745_reg.h" /* in SYSLIB */
-#define ADO_BA 0xfff09000
-#define ADO_RANGE 0x50
-
-/**********************************************************************************************************
- *
- * 8. Audio Interface Control Registers
- *
- **********************************************************************************************************/
-#define REG_ACTL_CON (ADO_BA + 0x00) /* Audio controller control register */
-#define REG_ACTL_RESET (ADO_BA + 0x04) /* Sub block reset control register */
-#define REG_ACTL_RDSTB (ADO_BA + 0x08) /* DMA destination base address register for record */
-#define REG_ACTL_RDST_LENGTH (ADO_BA + 0x0C) /* DMA destination length register for record */
-#define REG_ACTL_RSR (ADO_BA + 0x14) /* Record status register */
-#define REG_ACTL_PDSTB (ADO_BA + 0x18) /* DMA destination base address register for play */
-#define REG_ACTL_PDST_LENGTH (ADO_BA + 0x1C) /* DMA destination length register for play */
-#define REG_ACTL_PDSTC (ADO_BA + 0x20)
-#define REG_ACTL_PSR (ADO_BA + 0x24) /* Play status register */
-#define REG_ACTL_IISCON (ADO_BA + 0x28) /* IIS control register */
-#define REG_ACTL_ACCON (ADO_BA + 0x2C) /* AC-link control register */
-#define REG_ACTL_ACOS0 (ADO_BA + 0x30) /* AC-link out slot 0 */
-#define REG_ACTL_ACOS1 (ADO_BA + 0x34) /* AC-link out slot 1 */
-#define REG_ACTL_ACOS2 (ADO_BA + 0x38) /* AC-link out slot 2 */
-#define REG_ACTL_ACIS0 (ADO_BA + 0x3C) /* AC-link in slot 0 */
-#define REG_ACTL_ACIS1 (ADO_BA + 0x40) /* AC-link in slot 1 */
-#define REG_ACTL_ACIS2 (ADO_BA + 0x44) /* AC-link in slot 2 */
-
-
-
-#define AU_PLAY_INT_NUM 6
-#define AU_REC_INT_NUM 6
-#define GPIO_INT_NUM 4
-
-#define USED_GPIO_NUM 5
-
-#define MISCR 0xC
-#define PADMFC 0x20
-#define DCCS 0x5000
-#define DEVICE_CTRL 0x5004
-
-
-/* bit definition of REG_ACTL_CON register */
-#define AUDCLK_EN 0x8000
-#define PFIFO_EN 0x4000
-#define RFIFO_EN 0x2000
-#define R_DMA_IRQ 0x1000
-#define T_DMA_IRQ 0x0800
-#define IIS_AC_PIN_SEL 0x0100
-#define FIFO_TH 0x0080
-#define DMA_EN 0x0040
-#define DAC_EN 0x0020
-#define ADC_EN 0x0010
-#define M80_EN 0x0008
-#define ACLINK_EN 0x0004
-#define IIS_EN 0x0002
-#define AUDIO_EN 0x0001
-
-/* bit definition of REG_ACTL_RESET register */
-#define W5691_PLAY 0x20000
-#define ACTL_RESET_BIT 0x10000
-#define RECORD_RIGHT_CHNNEL 0x8000
-#define RECORD_LEFT_CHNNEL 0x4000
-#define PLAY_RIGHT_CHNNEL 0x2000
-#define PLAY_LEFT_CHNNEL 0x1000
-#define DAC_PLAY 0x0800
-#define ADC_RECORD 0x0400
-#define M80_PLAY 0x0200
-#define AC_RECORD 0x0100
-#define AC_PLAY 0x0080
-#define IIS_RECORD 0x0040
-#define IIS_PLAY 0x0020
-#define DAC_RESET 0x0010
-#define ADC_RESET 0x0008
-#define M80_RESET 0x0004
-#define AC_RESET 0x0002
-#define IIS_RESET 0x0001
-
-/* bit definition of REG_ACTL_ACCON register */
-#define AC_BCLK_PU_EN 0x20
-#define AC_R_FINISH 0x10
-#define AC_W_FINISH 0x08
-#define AC_W_RES 0x04
-#define AC_C_RES 0x02
-
-/* bit definition of REG_ACTL_RSR register */
-#define R_FIFO_EMPTY 0x04
-#define R_DMA_END_IRQ 0x02
-#define R_DMA_MIDDLE_IRQ 0x01
-
-/* bit definition of REG_ACTL_PSR register */
-#define P_FIFO_EMPTY 0x04
-#define P_DMA_END_IRQ 0x02
-#define P_DMA_MIDDLE_IRQ 0x01
-
-/* bit definition of REG_ACTL_M80CON register */
-#define X86_PCM_TRANS 0x10000
-#define BITS16 0x400
-#define MA3_W5691 0x200
-#define W_IF13_ACT 0x100
-#define BUSY 0x80
-#define R_IF11_ACT 0x40
-#define R_IF10_ACT 0x20
-#define W_IF12_ACT 0x10
-#define W_IF11_ACT 0x08
-#define W_IF10_ACT 0x04
-#define SOFT_CON 0x02
-#define W_GFIFO 0x20000
-
-#define CLK_DIV 0xF800
-
-#define SOFT_CON_A0 0x0
-#define SOFT_CON_A1 0x100
-#define SOFT_CON_R 0x200
-#define SOFT_CON_W 0x400
-#define SOFT_CON_CS 0x800
-#define SOFT_CON_REQ 0x1000
-#define SOFT_CON_REL 0x2000
-
-/* bit definition of REG_ACTL_ADCON register */
-#define ADC_ZCD_EN 0x8
-#define ADC_MUTE 0x2
-
-/* bit definition of REG_ACTL_DACON register */
-#define DAC1_OEB 0x2000
-#define DAC0_OEB 0x1000
-#define DAC_ZCD_EN 0x8
-#define DAC_MUTE 0x2
-
-#define AD_DA_48000 (0x0 << 4)
-#define AD_DA_44100 (0x1 << 4)
-#define AD_DA_32000 (0x2 << 4)
-#define AD_DA_24000 (0x3 << 4)
-#define AD_DA_22050 (0x4 << 4)
-#define AD_DA_16000 (0x5 << 4)
-#define AD_DA_12000 (0x6 << 4)
-#define AD_DA_11025 (0x7 << 4)
-#define AD_DA_8000 (0x8 << 4)
-
-#endif /* _W90N745_AUDIO_REGS_H_ */
-
-
+/************************************************************************************************** + * + * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved. + * + * FILENAME + * w90n745_Audio_REGS.H + * + * VERSION + * 1.0 + * + * DESCRIPTION + * This file contains the register map of W90N710 audio controller. + * + * HISTORY + * 05/26/2004 Ver 1.0 Created by PC30 YCHuang + * 11/24/2005 Ver 1.1 Modified by PC34 QFu + * + * REMARK + * None + * + *************************************************************************************************/ +#ifndef _W90N745_AUDIO_REGS_H_ +#define _W90N745_AUDIO_REGS_H_ + +#define REG_CLKSEL 0xfff0000c + +#define GPIO_BA 0xFFF83000 +/********************************************************************************************************** + * + * 4. GPIO Control Registers + * + **********************************************************************************************************/ +/* GPIO Pins */ +#define REG_GPIO_CFG (GPIO_BA+0x00) /* GPIO Pins Output Enable Control Register */ +#define REG_GPIO_DIR (GPIO_BA+0x04) /* GPIO Pins Data Register */ +#define REG_GPIO_DATAOUT (GPIO_BA+0x08) /* GPIO Pins Status Register */ + + +/* GPIO-A Pins */ +#define REG_GPIOA_OE (GPIO_BA+0x20) /* GPIO-A Pins Output Enable Control Register */ +#define REG_GPIOA_DAT (GPIO_BA+0x24) /* GPIO-A Pins Data Register */ +#define REG_GPIOA_STS (GPIO_BA+0x28) /* GPIO-A Pins Status Register */ +#define REG_GPIOA_PE (GPIO_BA+0x2c) /* GPIO-A Pull-Up/Down Enable Control Register */ + +/* GPIO-B Pins */ +#define REG_GPIOB_OE (GPIO_BA+0x30) /* GPIO-B Pins Output Enable Control Register */ +#define REG_GPIOB_DAT (GPIO_BA+0x34) /* GPIO-B Pins Data Register */ +#define REG_GPIOB_STS (GPIO_BA+0x38) /* GPIO-B Pins Status Register */ +#define REG_GPIOB_PE (GPIO_BA+0x3c) /* GPIO-B Pull-Up/Down Enable Control Register */ + +/* GPIO-S Pins */ +#define REG_GPIOS_OE (GPIO_BA+0x40) /* GPIO-S Pins Output Enable Control Register */ +#define REG_GPIOS_DAT (GPIO_BA+0x44) /* GPIO-S Pins Data Register */ +#define REG_GPIOS_STS (GPIO_BA+0x48) /* GPIO-S Pins Status Register */ +#define REG_GPIOS_PE (GPIO_BA+0x4c) /* GPIO-S Pull-Up/Down Enable Control Register */ + + +/* to be modified in future */ +//#include "w90n745_reg.h" /* in SYSLIB */ +#define ADO_BA 0xfff09000 +#define ADO_RANGE 0x50 + +/********************************************************************************************************** + * + * 8. Audio Interface Control Registers + * + **********************************************************************************************************/ +#define REG_ACTL_CON (ADO_BA + 0x00) /* Audio controller control register */ +#define REG_ACTL_RESET (ADO_BA + 0x04) /* Sub block reset control register */ +#define REG_ACTL_RDSTB (ADO_BA + 0x08) /* DMA destination base address register for record */ +#define REG_ACTL_RDST_LENGTH (ADO_BA + 0x0C) /* DMA destination length register for record */ +#define REG_ACTL_RSR (ADO_BA + 0x14) /* Record status register */ +#define REG_ACTL_PDSTB (ADO_BA + 0x18) /* DMA destination base address register for play */ +#define REG_ACTL_PDST_LENGTH (ADO_BA + 0x1C) /* DMA destination length register for play */ +#define REG_ACTL_PDSTC (ADO_BA + 0x20) +#define REG_ACTL_PSR (ADO_BA + 0x24) /* Play status register */ +#define REG_ACTL_IISCON (ADO_BA + 0x28) /* IIS control register */ +#define REG_ACTL_ACCON (ADO_BA + 0x2C) /* AC-link control register */ +#define REG_ACTL_ACOS0 (ADO_BA + 0x30) /* AC-link out slot 0 */ +#define REG_ACTL_ACOS1 (ADO_BA + 0x34) /* AC-link out slot 1 */ +#define REG_ACTL_ACOS2 (ADO_BA + 0x38) /* AC-link out slot 2 */ +#define REG_ACTL_ACIS0 (ADO_BA + 0x3C) /* AC-link in slot 0 */ +#define REG_ACTL_ACIS1 (ADO_BA + 0x40) /* AC-link in slot 1 */ +#define REG_ACTL_ACIS2 (ADO_BA + 0x44) /* AC-link in slot 2 */ + + + +#define AU_PLAY_INT_NUM 6 +#define AU_REC_INT_NUM 6 +#define GPIO_INT_NUM 4 + +#define USED_GPIO_NUM 5 + +#define MISCR 0xC +#define PADMFC 0x20 +#define DCCS 0x5000 +#define DEVICE_CTRL 0x5004 + + +/* bit definition of REG_ACTL_CON register */ +#define AUDCLK_EN 0x8000 +#define PFIFO_EN 0x4000 +#define RFIFO_EN 0x2000 +#define R_DMA_IRQ 0x1000 +#define T_DMA_IRQ 0x0800 +#define IIS_AC_PIN_SEL 0x0100 +#define FIFO_TH 0x0080 +#define DMA_EN 0x0040 +#define DAC_EN 0x0020 +#define ADC_EN 0x0010 +#define M80_EN 0x0008 +#define ACLINK_EN 0x0004 +#define IIS_EN 0x0002 +#define AUDIO_EN 0x0001 + +/* bit definition of REG_ACTL_RESET register */ +#define W5691_PLAY 0x20000 +#define ACTL_RESET_BIT 0x10000 +#define RECORD_RIGHT_CHNNEL 0x8000 +#define RECORD_LEFT_CHNNEL 0x4000 +#define PLAY_RIGHT_CHNNEL 0x2000 +#define PLAY_LEFT_CHNNEL 0x1000 +#define DAC_PLAY 0x0800 +#define ADC_RECORD 0x0400 +#define M80_PLAY 0x0200 +#define AC_RECORD 0x0100 +#define AC_PLAY 0x0080 +#define IIS_RECORD 0x0040 +#define IIS_PLAY 0x0020 +#define DAC_RESET 0x0010 +#define ADC_RESET 0x0008 +#define M80_RESET 0x0004 +#define AC_RESET 0x0002 +#define IIS_RESET 0x0001 + +/* bit definition of REG_ACTL_ACCON register */ +#define AC_BCLK_PU_EN 0x20 +#define AC_R_FINISH 0x10 +#define AC_W_FINISH 0x08 +#define AC_W_RES 0x04 +#define AC_C_RES 0x02 + +/* bit definition of REG_ACTL_RSR register */ +#define R_FIFO_EMPTY 0x04 +#define R_DMA_END_IRQ 0x02 +#define R_DMA_MIDDLE_IRQ 0x01 + +/* bit definition of REG_ACTL_PSR register */ +#define P_FIFO_EMPTY 0x04 +#define P_DMA_END_IRQ 0x02 +#define P_DMA_MIDDLE_IRQ 0x01 + +/* bit definition of REG_ACTL_M80CON register */ +#define X86_PCM_TRANS 0x10000 +#define BITS16 0x400 +#define MA3_W5691 0x200 +#define W_IF13_ACT 0x100 +#define BUSY 0x80 +#define R_IF11_ACT 0x40 +#define R_IF10_ACT 0x20 +#define W_IF12_ACT 0x10 +#define W_IF11_ACT 0x08 +#define W_IF10_ACT 0x04 +#define SOFT_CON 0x02 +#define W_GFIFO 0x20000 + +#define CLK_DIV 0xF800 + +#define SOFT_CON_A0 0x0 +#define SOFT_CON_A1 0x100 +#define SOFT_CON_R 0x200 +#define SOFT_CON_W 0x400 +#define SOFT_CON_CS 0x800 +#define SOFT_CON_REQ 0x1000 +#define SOFT_CON_REL 0x2000 + +/* bit definition of REG_ACTL_ADCON register */ +#define ADC_ZCD_EN 0x8 +#define ADC_MUTE 0x2 + +/* bit definition of REG_ACTL_DACON register */ +#define DAC1_OEB 0x2000 +#define DAC0_OEB 0x1000 +#define DAC_ZCD_EN 0x8 +#define DAC_MUTE 0x2 + +#define AD_DA_48000 (0x0 << 4) +#define AD_DA_44100 (0x1 << 4) +#define AD_DA_32000 (0x2 << 4) +#define AD_DA_24000 (0x3 << 4) +#define AD_DA_22050 (0x4 << 4) +#define AD_DA_16000 (0x5 << 4) +#define AD_DA_12000 (0x6 << 4) +#define AD_DA_11025 (0x7 << 4) +#define AD_DA_8000 (0x8 << 4) + +#endif /* _W90N745_AUDIO_REGS_H_ */ + + diff --git a/uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.c b/uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.c index 87cc6a9..3e31e20 100644 --- a/uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.c +++ b/uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.c @@ -1,677 +1,677 @@ -/****************************************************************************
- *
- * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved.
- *
- *
- * FILENAME
- * w90n745_I2S.c
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * IIS for PCM3003E codec
- *
- * DATA STRUCTURES
- * None
- *
- * FUNCTIONS
- *
- * HISTORY
- * 2004.07.16 Created by Shih-Jen Lu
- * 2005.11.24 Modified by PC34 QFu
- *
- * REMARK
- * None
- *
- **************************************************************************/
-#include <linux/soundcard.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "w90n745_audio_regs.h"
-#include "w90n745_audio.h"
-
-#include "w90n745_i2s.h"
-
-//#define I2S_DEBUG
-//#define I2S_DEBUG_ENTER_LEAVE
-//#define I2S_DEBUG_MSG
-//#define I2S_DEBUG_MSG2
-
-
-#ifdef I2S_DEBUG
-#define DBG(fmt, arg...) printk(fmt, ##arg)
-#else
-#define DBG(fmt, arg...)
-#endif
-
-#ifdef I2S_DEBUG_ENTER_LEAVE
-#define ENTER() DBG("[%-10s] : Enter\n", __FUNCTION__)
-#define LEAVE() DBG("[%-10s] : Leave\n", __FUNCTION__)
-#else
-#define ENTER()
-#define LEAVE()
-#endif
-
-#ifdef I2S_DEBUG_MSG
-#define MSG(fmt) DBG("[%-10s] : "fmt, __FUNCTION__)
-#else
-#define MSG(fmt)
-#endif
-
-#ifdef I2S_DEBUG_MSG2
-#define MSG2(fmt, arg...) DBG("[%-10s] : "fmt, __FUNCTION__, ##arg)
-#else
-#define MSG2(fmt, arg...)
-#endif
-
-static AUDIO_T _tIIS;
-
-#define AUDIO_WRITE(addr, val) writel(val, addr)
-#define AUDIO_READ(addr) readl(addr)
-
-#define Delay(time) udelay(time * 10)
-
-#define MSB_FORMAT 1
-#define IIS_FORMAT 2
-
-static int _bIISActive = 0;
-static UINT32 _uIISCR = 0;
-
-#define WMDEVID 0
-
-#define UINT8 unsigned char
-
-/*----- set data format -----*/
-static void IIS_Set_Data_Format(int choose_format)
-{
-
- ENTER();
-
- switch(choose_format){
- case IIS_FORMAT: _uIISCR = _uIISCR | IIS;
- break;
- case MSB_FORMAT: _uIISCR = _uIISCR | MSB_Justified;
- break;
- default:break;
- }
- AUDIO_WRITE(REG_ACTL_IISCON,_uIISCR);
-
- LEAVE();
-}
-
-/*----- set sample Frequency -----*/
-static void IIS_Set_Sample_Frequency(int choose_sf)
-{
-
- ENTER();
-
- switch (choose_sf)
- {
- case AU_SAMPLE_RATE_8000: //8KHz
- _uIISCR = _uIISCR | FS_256 | SCALE_4 | BCLK_48;
-
- break;
- case AU_SAMPLE_RATE_11025: //11.025KHz
- _uIISCR = _uIISCR | FS_256 | SCALE_4 | BCLK_48;
-
- break;
- case AU_SAMPLE_RATE_16000: //16KHz
- _uIISCR = _uIISCR | FS_256 | SCALE_2 | BCLK_48;
-
- break;
- case AU_SAMPLE_RATE_22050: //22.05KHz
- _uIISCR = _uIISCR | FS_256 | SCALE_3 | BCLK_32;
-
- break;
- case AU_SAMPLE_RATE_24000: //24KHz
- _uIISCR = _uIISCR | FS_256 | SCALE_2 | BCLK_32;
-
- break;
- case AU_SAMPLE_RATE_32000: //32KHz
- _uIISCR = _uIISCR | SCALE_1 | FS_256 | BCLK_48;
-
- break;
- case AU_SAMPLE_RATE_44100: //44.1KHz
- _uIISCR = _uIISCR | SCALE_1 | FS_256 | BCLK_48;
-
- break;
- case AU_SAMPLE_RATE_48000: //48KHz
- _uIISCR = _uIISCR | FS_256 | SCALE_1 | BCLK_32;
-
- break;
- default:break;
- }
- AUDIO_WRITE(REG_ACTL_IISCON,_uIISCR);
-
- if(choose_sf == AU_SAMPLE_RATE_44100 || choose_sf ==AU_SAMPLE_RATE_22050 || choose_sf ==AU_SAMPLE_RATE_11025 ){
- //outpw(REG_APLLCON, 0x642D);//16.934
- //outpw(REG_CLKDIV0, (inpw(REG_CLKDIV0) & 0xFF0FFFFF) | 0x300000);
- AUDIO_WRITE(0xfff00010, 0x2601);//PLLCON 390Mhz
- AUDIO_WRITE(0xfff00014, 0x116);// divide by 23
- }else
- {
- AUDIO_WRITE(0xfff00010, 0x2f01);//PLLCON 480Mhz
- AUDIO_WRITE(0xfff00014, 0x126);// divide by 39
- }
-
- LEAVE();
-}
-
-static INT iis_reset(void)
-{
- ENTER();
-
- AUDIO_WRITE(REG_CLKSEL, AUDIO_READ(REG_CLKSEL) | 0x10000);
-
- AUDIO_WRITE(0xFFF83000,0x155);//GPIO_CFG0 PT0CFG0~4
- AUDIO_WRITE(0xFFF83004,0x1d);//GPIO1:In GPIO0,2,3,4:Out
-
- /* reset audio interface */
- AUDIO_WRITE(REG_ACTL_RESET,AUDIO_READ(REG_ACTL_RESET) | ACTL_RESET_BIT);
- Delay(100);
- AUDIO_WRITE(REG_ACTL_RESET,AUDIO_READ(REG_ACTL_RESET) & ~ACTL_RESET_BIT);
- Delay(100);
-
- /* reset IIS interface */
- AUDIO_WRITE(REG_ACTL_RESET,AUDIO_READ(REG_ACTL_RESET) | IIS_RESET);
- Delay(100);
- AUDIO_WRITE(REG_ACTL_RESET,AUDIO_READ(REG_ACTL_RESET) & ~IIS_RESET);
- Delay(100);
-
- /* enable audio controller and IIS interface */
- AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ (REG_ACTL_CON) | AUDCLK_EN | PFIFO_EN | DMA_EN | IIS_EN | AUDIO_EN | RFIFO_EN | T_DMA_IRQ | R_DMA_IRQ);
-
-#if 0
- /* use GPIO 17 18 19 as L3 interface control pin */
- //writew(REG_GPIO_OE,readw(REG_GPIO_OE) & ~(1 << L3MODE_GPIO_NUM | 1<< L3CLOCK_GPIO_NUM | 1<< L3DATA_GPIO_NUM));
- AUDIO_WRITE(REG_GPIO_CFG,AUDIO_READ(REG_GPIO_CFG) & ~(0x3F<<14));
- AUDIO_WRITE(REG_GPIO_DIR,AUDIO_READ(REG_GPIO_DIR) | L3MODE_GPIO_NUM | L3CLOCK_GPIO_NUM | L3DATA_GPIO_NUM);
-
- /* set volume, dsp power up and no de-emph.no mute of external codec, from L3 */
-#endif
-
- _uIISCR = 0;
-
- LEAVE();
-
- return 0;
-}
-
-
-VOID i2sSetPlaySampleRate(INT nSamplingRate)
-{
- _tIIS.nPlaySamplingRate = nSamplingRate;
-}
-
-VOID i2sSetRecordSampleRate(INT nSamplingRate)
-{
- _tIIS.nRecSamplingRate = nSamplingRate;
-}
-
-
-VOID i2sSetPlayCallBackFunction(AU_CB_FUN_T fnCallBack)
-{
- _tIIS.fnPlayCallBack = fnCallBack;
-}
-
-VOID i2sSetRecordCallBackFunction(AU_CB_FUN_T fnCallBack)
-{
- _tIIS.fnRecCallBack = fnCallBack;
-}
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* i2sStartPlay */
-/* */
-/* DESCRIPTION */
-/* Start IIS playback. */
-/* */
-/* INPUTS */
-/* fnCallBack client program provided callback function. The audio */
-/* driver will call back to get next block of PCM data */
-/* nSamplingRate the playback sampling rate. Supported sampling */
-/* rate are 48000, 44100, 32000, 24000, 22050, 16000, */
-/* 11025, and 8000 Hz */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static int i2sStartPlay(AU_CB_FUN_T fnCallBack, INT nSamplingRate,
- INT nChannels)
-{
- INT nStatus /* ,L3status */;
-
- ENTER();
-
- if (_bIISActive & IIS_PLAY_ACTIVE){
- MSG("IIS already playing\n");
- return ERR_IIS_PLAY_ACTIVE; /* IIS was playing */
- }
-
- //printk("SamplingRate : %d Channels : %d\n", nSamplingRate, nChannels);
-
- if (_bIISActive == 0)
- {
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~ PLAY_LEFT_CHNNEL & ~ PLAY_RIGHT_CHNNEL);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | PLAY_RIGHT_CHNNEL);
- if (nChannels == AU_CH_STEREO)
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | PLAY_LEFT_CHNNEL);
- nStatus = iis_reset();
- if (nStatus < 0)
- return nStatus;
- }
-
-// enable_irq(AU_PLAY_INT_NUM);
- Enable_Int(AU_PLAY_INT_NUM);
-
- i2sSetPlayCallBackFunction(fnCallBack);
- i2sSetPlaySampleRate(nSamplingRate);
-
-#if 0
- /* set play sampling rate and data format */
- //L3status = L3_Set_Sample_Frequency(nSamplingRate);
- //L3status = L3status | L3_Set_Data_Format(data_format);
-
- //L3_Set_Data(EX_DAC_On);
- //L3_Set_Status(L3status);
-#endif
-
-
- IIS_Set_Sample_Frequency(nSamplingRate);
- IIS_Set_Data_Format(MSB_FORMAT);
-
-
- /* set DMA play destination base address */
- AUDIO_WRITE(REG_ACTL_PDSTB, _tIIS.uPlayBufferAddr);
-
- /* set DMA play buffer length */
- AUDIO_WRITE(REG_ACTL_PDST_LENGTH, _tIIS.uPlayBufferLength);
-
- MSG2("DMA Buffer : %x, Length : %x\n", _tIIS.uPlayBufferAddr,_tIIS.uPlayBufferLength);
-
- /* call back to fill DMA play buffer */
- //_tIIS.fnPlayCallBack((UINT8 *)_tIIS.uDMABufferAddr, _tIIS.uDMABufferLength/2);
- //_tIIS.fnPlayCallBack((UINT8 *)(_tIIS.uDMABufferAddr + _tIIS.uDMABufferLength/2),
- // _tIIS.uDMABufferLength/2);
-
- /* start playing */
- MSG("IIS start playing...\n");
- AUDIO_WRITE(REG_ACTL_PSR, 0x3);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | IIS_PLAY);
- _bIISActive |= IIS_PLAY_ACTIVE;
-
- LEAVE();
-
- return 0;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* i2sStopPlay */
-/* */
-/* DESCRIPTION */
-/* Stop IIS playback immdediately. */
-/* */
-/* INPUTS */
-/* None */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static void i2sStopPlay(void)
-{
- ENTER();
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(PLAY_RIGHT_CHNNEL | PLAY_LEFT_CHNNEL));
-
- if (!(_bIISActive & IIS_PLAY_ACTIVE))
- return;
-
- MSG("IIS stop playing\n");
-
- /* stop playing */
- while( AUDIO_READ(REG_ACTL_RESET) & IIS_PLAY )
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~IIS_PLAY);
-
- _bIISActive &= ~IIS_PLAY_ACTIVE;
-
- /* disable audio play interrupt */
- if (!_bIISActive)
- Disable_Int(AU_PLAY_INT_NUM);
-
-
- LEAVE();
-
- return;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* i2sStartRecord */
-/* */
-/* DESCRIPTION */
-/* Start IIS record. */
-/* */
-/* INPUTS */
-/* fnCallBack client program provided callback function. The audio */
-/* driver will call back to deliver the newly recorded */
-/* block of PCM data */
-/* nSamplingRate the record sampling rate. Supported sampling */
-/* rate are 48000, 44100, 32000, 24000, 22050, 16000, */
-/* 11025, and 8000 Hz */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static int i2sStartRecord(AU_CB_FUN_T fnCallBack, INT nSamplingRate,
- INT nChannels)
-{
- INT nStatus /* ,L3status */;
-
- ENTER();
-
- if (_bIISActive & IIS_REC_ACTIVE)
- return ERR_IIS_REC_ACTIVE; /* IIS was recording */
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(RECORD_LEFT_CHNNEL & RECORD_RIGHT_CHNNEL));
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | RECORD_LEFT_CHNNEL);
- if (nChannels != 1)
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | RECORD_RIGHT_CHNNEL);
-
- if (_bIISActive == 0)
- {
- nStatus = iis_reset();
- if (nStatus < 0)
- return nStatus;
- }
-
- Enable_Int(AU_REC_INT_NUM);
-
- i2sSetRecordCallBackFunction(fnCallBack);
- i2sSetRecordSampleRate(nSamplingRate);
-
-#if 0
- /* set record sampling rate and data format */
- //L3status = L3_Set_Sample_Frequency(nSamplingRate);
- //L3status = L3status | L3_Set_Data_Format(MSB_FORMAT);
-
- //L3_Set_Data(EX_ADC_On);
- //L3_Set_Status(L3status);
-#endif
-
- IIS_Set_Sample_Frequency(nSamplingRate);
- IIS_Set_Data_Format(MSB_FORMAT);
-
-
-
- /* set DMA record destination base address */
- AUDIO_WRITE(REG_ACTL_RDSTB, _tIIS.uRecordBufferAddr);
-
- /* set DMA record buffer length */
- AUDIO_WRITE(REG_ACTL_RDST_LENGTH, _tIIS.uRecordBufferLength);
-
- /* start recording */
- MSG("IIS start recording...\n");
- AUDIO_WRITE(REG_ACTL_RSR, 0x3);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | IIS_RECORD);
- _bIISActive |= IIS_REC_ACTIVE;
-
- LEAVE();
-
- return 0;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* i2sStopRecord */
-/* */
-/* DESCRIPTION */
-/* Stop IIS record immediately. */
-/* */
-/* INPUTS */
-/* None */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static void i2sStopRecord(void)
-{
- ENTER();
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(RECORD_RIGHT_CHNNEL | RECORD_LEFT_CHNNEL));
-
- if (!(_bIISActive & IIS_REC_ACTIVE))
- return;
-
- MSG("IIS stop recording\n");
-
- /* stop recording */
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~IIS_RECORD);
-
- _bIISActive &= ~IIS_REC_ACTIVE;
- /* disable audio record interrupt */
- if (!_bIISActive)
- Disable_Int(AU_PLAY_INT_NUM);
-
-
- LEAVE();
-
- return;
-}
-
-
-/*************************************************************************/
-/* */
-/* FUNCTION */
-/* i2sSetPlayVolume */
-/* */
-/* DESCRIPTION */
-/* Set i2S left and right channel play volume. */
-/* */
-/* INPUTS */
-/* ucLeftVol play volume of left channel */
-/* ucRightVol play volume of left channel */
-/* 0: mute */
-/* 1: minimal volume */
-/* 31: maxmum volume */
-/* */
-/* OUTPUTS */
-/* None */
-/* */
-/* RETURN */
-/* 0 Success */
-/* Otherwise error */
-/* */
-/*************************************************************************/
-static int i2sSetPlayVolume(UINT32 ucLeftVol, UINT32 ucRightVol) //0~31
-{
- ENTER();
-
- if (ucLeftVol>31)
- ucLeftVol=31;
- if (ucRightVol>31)
- ucRightVol=31;
-
- //printk("Set IIS Play volume to : %d-%d\n", ucLeftVol, ucRightVol);
-
- _tIIS.sPlayVolume = 0x3F - ucLeftVol*2;
-
-#if 0
- /*----- Address Mode -----*/
- L3_Address_Mode(EX_1345ADDR | EX_DATA);//set the DATA(volumn,de-emphasis, mute, and power control)
- /*----- Data Transfer Mode -----*/
- L3_Data_Transfer_Mode((UINT8)_tIIS.sPlayVolume);
-#endif
-
- LEAVE();
-
- return 0;
-}
-
-static int i2sSetRecordVolume(UINT32 ucLeftVol, UINT32 ucRightVol)
-{
- ENTER();
-
- LEAVE();
-
- return 0;
-
-}
-
-static void i2sSetPlayBuffer(UINT32 uDMABufferAddr, UINT32 uDMABufferLength)
-{
- ENTER();
-
- _tIIS.uPlayBufferAddr = uDMABufferAddr;
- _tIIS.uPlayBufferLength = uDMABufferLength;
-
- LEAVE();
-}
-
-static void i2sSetRecordBuffer(UINT32 uDMABufferAddr, UINT32 uDMABufferLength)
-{
- ENTER();
-
- _tIIS.uRecordBufferAddr = uDMABufferAddr;
- _tIIS.uRecordBufferLength = uDMABufferLength;
-
- LEAVE();
-}
-
-static void iis_play_isr(void)
-{
- int bPlayLastBlock = 0;
-
- ENTER();
-
- MSG2("[DMA:S:%x,L:%x,C:%x]\n",
- AUDIO_READ(REG_ACTL_PDSTB),
- AUDIO_READ(REG_ACTL_PDST_LENGTH),
- AUDIO_READ(REG_ACTL_PDSTC));
-
-
- AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ(REG_ACTL_CON) | T_DMA_IRQ);
-
- if (AUDIO_READ(REG_ACTL_PSR) & P_DMA_MIDDLE_IRQ)
- {
- AUDIO_WRITE(REG_ACTL_PSR, P_DMA_MIDDLE_IRQ);
- bPlayLastBlock = _tIIS.fnPlayCallBack(_tIIS.uPlayBufferAddr,
- _tIIS.uPlayBufferLength/2);
- }
- else if (AUDIO_READ(REG_ACTL_PSR) & P_DMA_END_IRQ)
- {
- AUDIO_WRITE(REG_ACTL_PSR, P_DMA_END_IRQ);
- bPlayLastBlock = _tIIS.fnPlayCallBack(_tIIS.uPlayBufferAddr + _tIIS.uPlayBufferLength/2,
- _tIIS.uPlayBufferLength/2);
- }
-
-
- /* check whether the next block is ready. If not, stop play */
-
- if (bPlayLastBlock)
- {
- AUDIO_WRITE(REG_ACTL_PSR, P_DMA_MIDDLE_IRQ | P_DMA_END_IRQ);
-// i2sStopPlay();
- }
-
-
- LEAVE();
-
-}
-
-
-static void iis_rec_isr(void)
-{
- int bPlayLastBlock = 0;
-
- ENTER();
-
- AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ(REG_ACTL_CON) | R_DMA_IRQ);
-
- if (AUDIO_READ(REG_ACTL_RSR) & R_DMA_MIDDLE_IRQ)
- {
- AUDIO_WRITE(REG_ACTL_RSR, R_DMA_MIDDLE_IRQ);
- bPlayLastBlock = _tIIS.fnRecCallBack(_tIIS.uRecordBufferAddr, _tIIS.uRecordBufferLength/2);
- }
- else if (AUDIO_READ(REG_ACTL_RSR) & R_DMA_END_IRQ)
- {
- AUDIO_WRITE(REG_ACTL_RSR, R_DMA_END_IRQ);
- bPlayLastBlock = _tIIS.fnRecCallBack(_tIIS.uRecordBufferAddr + _tIIS.uRecordBufferLength/2,
- _tIIS.uRecordBufferLength/2);
- }
-
- /* check whether the next block is token away. If not, stop record */
-
- if (bPlayLastBlock)
- {
- AUDIO_WRITE(REG_ACTL_RSR, R_DMA_MIDDLE_IRQ | R_DMA_END_IRQ);
- }
-
- LEAVE();
-}
-
-
-INT i2sInit(VOID)
-{
- int nStatus = 0;
-
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~PLAY_LEFT_CHNNEL &~PLAY_RIGHT_CHNNEL);
- AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~RECORD_LEFT_CHNNEL &~RECORD_RIGHT_CHNNEL);
-
- nStatus = iis_reset();
- if (nStatus < 0)
- return nStatus;
-
- return 0;
-}
-
-static INT i2sGetCapacity(VOID)
-{
- return DSP_CAP_DUPLEX; /* support full duplex */
-}
-
-WB_AUDIO_CODEC_T wb_i2s_codec = {
- dev: AU_DEV_IIS,
- get_capacity: i2sGetCapacity,
- set_play_buffer: i2sSetPlayBuffer,
- set_record_buffer: i2sSetRecordBuffer,
- reset: i2sInit,
- start_play: i2sStartPlay,
- stop_play: i2sStopPlay,
- start_record: i2sStartRecord,
- stop_record: i2sStopRecord,
- set_play_volume: i2sSetPlayVolume,
- set_record_volume: i2sSetRecordVolume, /* not supprted */
- play_interrupt: iis_play_isr,
- record_interrupt: iis_rec_isr,
-};
+/**************************************************************************** + * + * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved. + * + * + * FILENAME + * w90n745_I2S.c + * + * VERSION + * 1.0 + * + * DESCRIPTION + * IIS for PCM3003E codec + * + * DATA STRUCTURES + * None + * + * FUNCTIONS + * + * HISTORY + * 2004.07.16 Created by Shih-Jen Lu + * 2005.11.24 Modified by PC34 QFu + * + * REMARK + * None + * + **************************************************************************/ +#include <linux/soundcard.h> +#include <linux/delay.h> +#include <asm/io.h> +#include <asm/irq.h> + +#include "w90n745_audio_regs.h" +#include "w90n745_audio.h" + +#include "w90n745_i2s.h" + +//#define I2S_DEBUG +//#define I2S_DEBUG_ENTER_LEAVE +//#define I2S_DEBUG_MSG +//#define I2S_DEBUG_MSG2 + + +#ifdef I2S_DEBUG +#define DBG(fmt, arg...) printk(fmt, ##arg) +#else +#define DBG(fmt, arg...) +#endif + +#ifdef I2S_DEBUG_ENTER_LEAVE +#define ENTER() DBG("[%-10s] : Enter\n", __FUNCTION__) +#define LEAVE() DBG("[%-10s] : Leave\n", __FUNCTION__) +#else +#define ENTER() +#define LEAVE() +#endif + +#ifdef I2S_DEBUG_MSG +#define MSG(fmt) DBG("[%-10s] : "fmt, __FUNCTION__) +#else +#define MSG(fmt) +#endif + +#ifdef I2S_DEBUG_MSG2 +#define MSG2(fmt, arg...) DBG("[%-10s] : "fmt, __FUNCTION__, ##arg) +#else +#define MSG2(fmt, arg...) +#endif + +static AUDIO_T _tIIS; + +#define AUDIO_WRITE(addr, val) writel(val, addr) +#define AUDIO_READ(addr) readl(addr) + +#define Delay(time) udelay(time * 10) + +#define MSB_FORMAT 1 +#define IIS_FORMAT 2 + +static int _bIISActive = 0; +static UINT32 _uIISCR = 0; + +#define WMDEVID 0 + +#define UINT8 unsigned char + +/*----- set data format -----*/ +static void IIS_Set_Data_Format(int choose_format) +{ + + ENTER(); + + switch(choose_format){ + case IIS_FORMAT: _uIISCR = _uIISCR | IIS; + break; + case MSB_FORMAT: _uIISCR = _uIISCR | MSB_Justified; + break; + default:break; + } + AUDIO_WRITE(REG_ACTL_IISCON,_uIISCR); + + LEAVE(); +} + +/*----- set sample Frequency -----*/ +static void IIS_Set_Sample_Frequency(int choose_sf) +{ + + ENTER(); + + switch (choose_sf) + { + case AU_SAMPLE_RATE_8000: //8KHz + _uIISCR = _uIISCR | FS_256 | SCALE_4 | BCLK_48; + + break; + case AU_SAMPLE_RATE_11025: //11.025KHz + _uIISCR = _uIISCR | FS_256 | SCALE_4 | BCLK_48; + + break; + case AU_SAMPLE_RATE_16000: //16KHz + _uIISCR = _uIISCR | FS_256 | SCALE_2 | BCLK_48; + + break; + case AU_SAMPLE_RATE_22050: //22.05KHz + _uIISCR = _uIISCR | FS_256 | SCALE_3 | BCLK_32; + + break; + case AU_SAMPLE_RATE_24000: //24KHz + _uIISCR = _uIISCR | FS_256 | SCALE_2 | BCLK_32; + + break; + case AU_SAMPLE_RATE_32000: //32KHz + _uIISCR = _uIISCR | SCALE_1 | FS_256 | BCLK_48; + + break; + case AU_SAMPLE_RATE_44100: //44.1KHz + _uIISCR = _uIISCR | SCALE_1 | FS_256 | BCLK_48; + + break; + case AU_SAMPLE_RATE_48000: //48KHz + _uIISCR = _uIISCR | FS_256 | SCALE_1 | BCLK_32; + + break; + default:break; + } + AUDIO_WRITE(REG_ACTL_IISCON,_uIISCR); + + if(choose_sf == AU_SAMPLE_RATE_44100 || choose_sf ==AU_SAMPLE_RATE_22050 || choose_sf ==AU_SAMPLE_RATE_11025 ){ + //outpw(REG_APLLCON, 0x642D);//16.934 + //outpw(REG_CLKDIV0, (inpw(REG_CLKDIV0) & 0xFF0FFFFF) | 0x300000); + AUDIO_WRITE(0xfff00010, 0x2601);//PLLCON 390Mhz + AUDIO_WRITE(0xfff00014, 0x116);// divide by 23 + }else + { + AUDIO_WRITE(0xfff00010, 0x2f01);//PLLCON 480Mhz + AUDIO_WRITE(0xfff00014, 0x126);// divide by 39 + } + + LEAVE(); +} + +static INT iis_reset(void) +{ + ENTER(); + + AUDIO_WRITE(REG_CLKSEL, AUDIO_READ(REG_CLKSEL) | 0x10000); + + AUDIO_WRITE(0xFFF83000,0x155);//GPIO_CFG0 PT0CFG0~4 + AUDIO_WRITE(0xFFF83004,0x1d);//GPIO1:In GPIO0,2,3,4:Out + + /* reset audio interface */ + AUDIO_WRITE(REG_ACTL_RESET,AUDIO_READ(REG_ACTL_RESET) | ACTL_RESET_BIT); + Delay(100); + AUDIO_WRITE(REG_ACTL_RESET,AUDIO_READ(REG_ACTL_RESET) & ~ACTL_RESET_BIT); + Delay(100); + + /* reset IIS interface */ + AUDIO_WRITE(REG_ACTL_RESET,AUDIO_READ(REG_ACTL_RESET) | IIS_RESET); + Delay(100); + AUDIO_WRITE(REG_ACTL_RESET,AUDIO_READ(REG_ACTL_RESET) & ~IIS_RESET); + Delay(100); + + /* enable audio controller and IIS interface */ + AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ (REG_ACTL_CON) | AUDCLK_EN | PFIFO_EN | DMA_EN | IIS_EN | AUDIO_EN | RFIFO_EN | T_DMA_IRQ | R_DMA_IRQ); + +#if 0 + /* use GPIO 17 18 19 as L3 interface control pin */ + //writew(REG_GPIO_OE,readw(REG_GPIO_OE) & ~(1 << L3MODE_GPIO_NUM | 1<< L3CLOCK_GPIO_NUM | 1<< L3DATA_GPIO_NUM)); + AUDIO_WRITE(REG_GPIO_CFG,AUDIO_READ(REG_GPIO_CFG) & ~(0x3F<<14)); + AUDIO_WRITE(REG_GPIO_DIR,AUDIO_READ(REG_GPIO_DIR) | L3MODE_GPIO_NUM | L3CLOCK_GPIO_NUM | L3DATA_GPIO_NUM); + + /* set volume, dsp power up and no de-emph.no mute of external codec, from L3 */ +#endif + + _uIISCR = 0; + + LEAVE(); + + return 0; +} + + +VOID i2sSetPlaySampleRate(INT nSamplingRate) +{ + _tIIS.nPlaySamplingRate = nSamplingRate; +} + +VOID i2sSetRecordSampleRate(INT nSamplingRate) +{ + _tIIS.nRecSamplingRate = nSamplingRate; +} + + +VOID i2sSetPlayCallBackFunction(AU_CB_FUN_T fnCallBack) +{ + _tIIS.fnPlayCallBack = fnCallBack; +} + +VOID i2sSetRecordCallBackFunction(AU_CB_FUN_T fnCallBack) +{ + _tIIS.fnRecCallBack = fnCallBack; +} + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* i2sStartPlay */ +/* */ +/* DESCRIPTION */ +/* Start IIS playback. */ +/* */ +/* INPUTS */ +/* fnCallBack client program provided callback function. The audio */ +/* driver will call back to get next block of PCM data */ +/* nSamplingRate the playback sampling rate. Supported sampling */ +/* rate are 48000, 44100, 32000, 24000, 22050, 16000, */ +/* 11025, and 8000 Hz */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static int i2sStartPlay(AU_CB_FUN_T fnCallBack, INT nSamplingRate, + INT nChannels) +{ + INT nStatus /* ,L3status */; + + ENTER(); + + if (_bIISActive & IIS_PLAY_ACTIVE){ + MSG("IIS already playing\n"); + return ERR_IIS_PLAY_ACTIVE; /* IIS was playing */ + } + + //printk("SamplingRate : %d Channels : %d\n", nSamplingRate, nChannels); + + if (_bIISActive == 0) + { + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~ PLAY_LEFT_CHNNEL & ~ PLAY_RIGHT_CHNNEL); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | PLAY_RIGHT_CHNNEL); + if (nChannels == AU_CH_STEREO) + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | PLAY_LEFT_CHNNEL); + nStatus = iis_reset(); + if (nStatus < 0) + return nStatus; + } + +// enable_irq(AU_PLAY_INT_NUM); + Enable_Int(AU_PLAY_INT_NUM); + + i2sSetPlayCallBackFunction(fnCallBack); + i2sSetPlaySampleRate(nSamplingRate); + +#if 0 + /* set play sampling rate and data format */ + //L3status = L3_Set_Sample_Frequency(nSamplingRate); + //L3status = L3status | L3_Set_Data_Format(data_format); + + //L3_Set_Data(EX_DAC_On); + //L3_Set_Status(L3status); +#endif + + + IIS_Set_Sample_Frequency(nSamplingRate); + IIS_Set_Data_Format(MSB_FORMAT); + + + /* set DMA play destination base address */ + AUDIO_WRITE(REG_ACTL_PDSTB, _tIIS.uPlayBufferAddr); + + /* set DMA play buffer length */ + AUDIO_WRITE(REG_ACTL_PDST_LENGTH, _tIIS.uPlayBufferLength); + + MSG2("DMA Buffer : %x, Length : %x\n", _tIIS.uPlayBufferAddr,_tIIS.uPlayBufferLength); + + /* call back to fill DMA play buffer */ + //_tIIS.fnPlayCallBack((UINT8 *)_tIIS.uDMABufferAddr, _tIIS.uDMABufferLength/2); + //_tIIS.fnPlayCallBack((UINT8 *)(_tIIS.uDMABufferAddr + _tIIS.uDMABufferLength/2), + // _tIIS.uDMABufferLength/2); + + /* start playing */ + MSG("IIS start playing...\n"); + AUDIO_WRITE(REG_ACTL_PSR, 0x3); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | IIS_PLAY); + _bIISActive |= IIS_PLAY_ACTIVE; + + LEAVE(); + + return 0; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* i2sStopPlay */ +/* */ +/* DESCRIPTION */ +/* Stop IIS playback immdediately. */ +/* */ +/* INPUTS */ +/* None */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static void i2sStopPlay(void) +{ + ENTER(); + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(PLAY_RIGHT_CHNNEL | PLAY_LEFT_CHNNEL)); + + if (!(_bIISActive & IIS_PLAY_ACTIVE)) + return; + + MSG("IIS stop playing\n"); + + /* stop playing */ + while( AUDIO_READ(REG_ACTL_RESET) & IIS_PLAY ) + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~IIS_PLAY); + + _bIISActive &= ~IIS_PLAY_ACTIVE; + + /* disable audio play interrupt */ + if (!_bIISActive) + Disable_Int(AU_PLAY_INT_NUM); + + + LEAVE(); + + return; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* i2sStartRecord */ +/* */ +/* DESCRIPTION */ +/* Start IIS record. */ +/* */ +/* INPUTS */ +/* fnCallBack client program provided callback function. The audio */ +/* driver will call back to deliver the newly recorded */ +/* block of PCM data */ +/* nSamplingRate the record sampling rate. Supported sampling */ +/* rate are 48000, 44100, 32000, 24000, 22050, 16000, */ +/* 11025, and 8000 Hz */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static int i2sStartRecord(AU_CB_FUN_T fnCallBack, INT nSamplingRate, + INT nChannels) +{ + INT nStatus /* ,L3status */; + + ENTER(); + + if (_bIISActive & IIS_REC_ACTIVE) + return ERR_IIS_REC_ACTIVE; /* IIS was recording */ + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(RECORD_LEFT_CHNNEL & RECORD_RIGHT_CHNNEL)); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | RECORD_LEFT_CHNNEL); + if (nChannels != 1) + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | RECORD_RIGHT_CHNNEL); + + if (_bIISActive == 0) + { + nStatus = iis_reset(); + if (nStatus < 0) + return nStatus; + } + + Enable_Int(AU_REC_INT_NUM); + + i2sSetRecordCallBackFunction(fnCallBack); + i2sSetRecordSampleRate(nSamplingRate); + +#if 0 + /* set record sampling rate and data format */ + //L3status = L3_Set_Sample_Frequency(nSamplingRate); + //L3status = L3status | L3_Set_Data_Format(MSB_FORMAT); + + //L3_Set_Data(EX_ADC_On); + //L3_Set_Status(L3status); +#endif + + IIS_Set_Sample_Frequency(nSamplingRate); + IIS_Set_Data_Format(MSB_FORMAT); + + + + /* set DMA record destination base address */ + AUDIO_WRITE(REG_ACTL_RDSTB, _tIIS.uRecordBufferAddr); + + /* set DMA record buffer length */ + AUDIO_WRITE(REG_ACTL_RDST_LENGTH, _tIIS.uRecordBufferLength); + + /* start recording */ + MSG("IIS start recording...\n"); + AUDIO_WRITE(REG_ACTL_RSR, 0x3); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) | IIS_RECORD); + _bIISActive |= IIS_REC_ACTIVE; + + LEAVE(); + + return 0; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* i2sStopRecord */ +/* */ +/* DESCRIPTION */ +/* Stop IIS record immediately. */ +/* */ +/* INPUTS */ +/* None */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static void i2sStopRecord(void) +{ + ENTER(); + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~(RECORD_RIGHT_CHNNEL | RECORD_LEFT_CHNNEL)); + + if (!(_bIISActive & IIS_REC_ACTIVE)) + return; + + MSG("IIS stop recording\n"); + + /* stop recording */ + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) & ~IIS_RECORD); + + _bIISActive &= ~IIS_REC_ACTIVE; + /* disable audio record interrupt */ + if (!_bIISActive) + Disable_Int(AU_PLAY_INT_NUM); + + + LEAVE(); + + return; +} + + +/*************************************************************************/ +/* */ +/* FUNCTION */ +/* i2sSetPlayVolume */ +/* */ +/* DESCRIPTION */ +/* Set i2S left and right channel play volume. */ +/* */ +/* INPUTS */ +/* ucLeftVol play volume of left channel */ +/* ucRightVol play volume of left channel */ +/* 0: mute */ +/* 1: minimal volume */ +/* 31: maxmum volume */ +/* */ +/* OUTPUTS */ +/* None */ +/* */ +/* RETURN */ +/* 0 Success */ +/* Otherwise error */ +/* */ +/*************************************************************************/ +static int i2sSetPlayVolume(UINT32 ucLeftVol, UINT32 ucRightVol) //0~31 +{ + ENTER(); + + if (ucLeftVol>31) + ucLeftVol=31; + if (ucRightVol>31) + ucRightVol=31; + + //printk("Set IIS Play volume to : %d-%d\n", ucLeftVol, ucRightVol); + + _tIIS.sPlayVolume = 0x3F - ucLeftVol*2; + +#if 0 + /*----- Address Mode -----*/ + L3_Address_Mode(EX_1345ADDR | EX_DATA);//set the DATA(volumn,de-emphasis, mute, and power control) + /*----- Data Transfer Mode -----*/ + L3_Data_Transfer_Mode((UINT8)_tIIS.sPlayVolume); +#endif + + LEAVE(); + + return 0; +} + +static int i2sSetRecordVolume(UINT32 ucLeftVol, UINT32 ucRightVol) +{ + ENTER(); + + LEAVE(); + + return 0; + +} + +static void i2sSetPlayBuffer(UINT32 uDMABufferAddr, UINT32 uDMABufferLength) +{ + ENTER(); + + _tIIS.uPlayBufferAddr = uDMABufferAddr; + _tIIS.uPlayBufferLength = uDMABufferLength; + + LEAVE(); +} + +static void i2sSetRecordBuffer(UINT32 uDMABufferAddr, UINT32 uDMABufferLength) +{ + ENTER(); + + _tIIS.uRecordBufferAddr = uDMABufferAddr; + _tIIS.uRecordBufferLength = uDMABufferLength; + + LEAVE(); +} + +static void iis_play_isr(void) +{ + int bPlayLastBlock = 0; + + ENTER(); + + MSG2("[DMA:S:%x,L:%x,C:%x]\n", + AUDIO_READ(REG_ACTL_PDSTB), + AUDIO_READ(REG_ACTL_PDST_LENGTH), + AUDIO_READ(REG_ACTL_PDSTC)); + + + AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ(REG_ACTL_CON) | T_DMA_IRQ); + + if (AUDIO_READ(REG_ACTL_PSR) & P_DMA_MIDDLE_IRQ) + { + AUDIO_WRITE(REG_ACTL_PSR, P_DMA_MIDDLE_IRQ); + bPlayLastBlock = _tIIS.fnPlayCallBack(_tIIS.uPlayBufferAddr, + _tIIS.uPlayBufferLength/2); + } + else if (AUDIO_READ(REG_ACTL_PSR) & P_DMA_END_IRQ) + { + AUDIO_WRITE(REG_ACTL_PSR, P_DMA_END_IRQ); + bPlayLastBlock = _tIIS.fnPlayCallBack(_tIIS.uPlayBufferAddr + _tIIS.uPlayBufferLength/2, + _tIIS.uPlayBufferLength/2); + } + + + /* check whether the next block is ready. If not, stop play */ + + if (bPlayLastBlock) + { + AUDIO_WRITE(REG_ACTL_PSR, P_DMA_MIDDLE_IRQ | P_DMA_END_IRQ); +// i2sStopPlay(); + } + + + LEAVE(); + +} + + +static void iis_rec_isr(void) +{ + int bPlayLastBlock = 0; + + ENTER(); + + AUDIO_WRITE(REG_ACTL_CON, AUDIO_READ(REG_ACTL_CON) | R_DMA_IRQ); + + if (AUDIO_READ(REG_ACTL_RSR) & R_DMA_MIDDLE_IRQ) + { + AUDIO_WRITE(REG_ACTL_RSR, R_DMA_MIDDLE_IRQ); + bPlayLastBlock = _tIIS.fnRecCallBack(_tIIS.uRecordBufferAddr, _tIIS.uRecordBufferLength/2); + } + else if (AUDIO_READ(REG_ACTL_RSR) & R_DMA_END_IRQ) + { + AUDIO_WRITE(REG_ACTL_RSR, R_DMA_END_IRQ); + bPlayLastBlock = _tIIS.fnRecCallBack(_tIIS.uRecordBufferAddr + _tIIS.uRecordBufferLength/2, + _tIIS.uRecordBufferLength/2); + } + + /* check whether the next block is token away. If not, stop record */ + + if (bPlayLastBlock) + { + AUDIO_WRITE(REG_ACTL_RSR, R_DMA_MIDDLE_IRQ | R_DMA_END_IRQ); + } + + LEAVE(); +} + + +INT i2sInit(VOID) +{ + int nStatus = 0; + + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~PLAY_LEFT_CHNNEL &~PLAY_RIGHT_CHNNEL); + AUDIO_WRITE(REG_ACTL_RESET, AUDIO_READ(REG_ACTL_RESET) &~RECORD_LEFT_CHNNEL &~RECORD_RIGHT_CHNNEL); + + nStatus = iis_reset(); + if (nStatus < 0) + return nStatus; + + return 0; +} + +static INT i2sGetCapacity(VOID) +{ + return DSP_CAP_DUPLEX; /* support full duplex */ +} + +WB_AUDIO_CODEC_T wb_i2s_codec = { + dev: AU_DEV_IIS, + get_capacity: i2sGetCapacity, + set_play_buffer: i2sSetPlayBuffer, + set_record_buffer: i2sSetRecordBuffer, + reset: i2sInit, + start_play: i2sStartPlay, + stop_play: i2sStopPlay, + start_record: i2sStartRecord, + stop_record: i2sStopRecord, + set_play_volume: i2sSetPlayVolume, + set_record_volume: i2sSetRecordVolume, /* not supprted */ + play_interrupt: iis_play_isr, + record_interrupt: iis_rec_isr, +}; diff --git a/uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.h b/uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.h index 3b9aef5..0735025 100644 --- a/uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.h +++ b/uClinux-2.4.20-uc1/drivers/sound/w90n745_i2s.h @@ -1,69 +1,69 @@ -/**************************************************************************************************
- *
- * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved.
- *
- * FILENAME
- * w90n745_i2s.h
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * This file contains the register map of IIS audio interface
- *
- * HISTORY
- * 02/09/2004 Ver 1.0 Created by PC31 SJLu
- *
- * REMARK
- * None
- *
- *************************************************************************************************/
-#ifndef _W90N745_I2S_H_
-#define _W90N745_I2S_H_
-
-/*----- bit definition of REG_ACTL_IISCON register -----*/
-#define IIS 0x0
-#define MSB_Justified 0x0008
-#define SCALE_1 0x0
-#define SCALE_2 0x10000
-#define SCALE_3 0x20000
-#define SCALE_4 0x30000
-#define SCALE_5 0x40000
-#define SCALE_6 0x50000
-#define SCALE_7 0x60000
-#define SCALE_8 0x70000
-#define SCALE_10 0x90000
-#define SCALE_12 0xB0000
-#define SCALE_14 0xD0000
-#define SCALE_16 0xF0000
-#define FS_384 0x20
-#define FS_256 0x0
-#define BCLK_32 0x00
-#define BCLK_48 0x40
-
-/* bit definition of L3DATA register */
-#define EX_256FS 0x20 /*-- system clock --*/
-#define EX_384FS 0x10
-#define EX_IIS 0x00 /*-- data input format --*/
-#define EX_MSB 0x08
-#define EX_1345ADDR 0x14 //The address of the UDA1345TS
-#define EX_STATUS 0x02 //data transfer type (STATUS)
-#define EX_DATA 0x00 //data transfer type (DATA)
-#define EX_ADC_On 0xC2 //turn on the ADC
-#define EX_DAC_On 0xC1 //turn on the DAC
-
-/*----- GPIO NUM -----*/
-#define L3MODE_GPIO_NUM (1<<17)
-#define L3CLOCK_GPIO_NUM (1<<18)
-#define L3DATA_GPIO_NUM (1<<19)
-
-#define MSB_FORMAT 1
-#define IIS_FORMAT 2
-
-#define IIS_ACTIVE 0x1
-#define IIS_PLAY_ACTIVE 0x2
-#define IIS_REC_ACTIVE 0x4
-
-#endif /* _W90N745_I2S_H_ */
-
-
+/************************************************************************************************** + * + * Copyright (c) 2004 - 2007 Winbond Electronics Corp. All rights reserved. + * + * FILENAME + * w90n745_i2s.h + * + * VERSION + * 1.0 + * + * DESCRIPTION + * This file contains the register map of IIS audio interface + * + * HISTORY + * 02/09/2004 Ver 1.0 Created by PC31 SJLu + * + * REMARK + * None + * + *************************************************************************************************/ +#ifndef _W90N745_I2S_H_ +#define _W90N745_I2S_H_ + +/*----- bit definition of REG_ACTL_IISCON register -----*/ +#define IIS 0x0 +#define MSB_Justified 0x0008 +#define SCALE_1 0x0 +#define SCALE_2 0x10000 +#define SCALE_3 0x20000 +#define SCALE_4 0x30000 +#define SCALE_5 0x40000 +#define SCALE_6 0x50000 +#define SCALE_7 0x60000 +#define SCALE_8 0x70000 +#define SCALE_10 0x90000 +#define SCALE_12 0xB0000 +#define SCALE_14 0xD0000 +#define SCALE_16 0xF0000 +#define FS_384 0x20 +#define FS_256 0x0 +#define BCLK_32 0x00 +#define BCLK_48 0x40 + +/* bit definition of L3DATA register */ +#define EX_256FS 0x20 /*-- system clock --*/ +#define EX_384FS 0x10 +#define EX_IIS 0x00 /*-- data input format --*/ +#define EX_MSB 0x08 +#define EX_1345ADDR 0x14 //The address of the UDA1345TS +#define EX_STATUS 0x02 //data transfer type (STATUS) +#define EX_DATA 0x00 //data transfer type (DATA) +#define EX_ADC_On 0xC2 //turn on the ADC +#define EX_DAC_On 0xC1 //turn on the DAC + +/*----- GPIO NUM -----*/ +#define L3MODE_GPIO_NUM (1<<17) +#define L3CLOCK_GPIO_NUM (1<<18) +#define L3DATA_GPIO_NUM (1<<19) + +#define MSB_FORMAT 1 +#define IIS_FORMAT 2 + +#define IIS_ACTIVE 0x1 +#define IIS_PLAY_ACTIVE 0x2 +#define IIS_REC_ACTIVE 0x4 + +#endif /* _W90N745_I2S_H_ */ + + |