diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/soc/wmt/wmt-i2s.c')
-rwxr-xr-x | ANDROID_3.4.5/sound/soc/wmt/wmt-i2s.c | 1105 |
1 files changed, 0 insertions, 1105 deletions
diff --git a/ANDROID_3.4.5/sound/soc/wmt/wmt-i2s.c b/ANDROID_3.4.5/sound/soc/wmt/wmt-i2s.c deleted file mode 100755 index 643d25e2..00000000 --- a/ANDROID_3.4.5/sound/soc/wmt/wmt-i2s.c +++ /dev/null @@ -1,1105 +0,0 @@ -/*++ - * linux/sound/soc/wmt/wmt-i2s.c - * WonderMedia I2S audio driver for ALSA - * - * Copyright c 2010 WonderMedia Technologies, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * WonderMedia Technologies, Inc. - * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C ---*/ - - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <asm/irq.h> -#include <linux/delay.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/initval.h> -#include <sound/soc.h> - -#include <linux/gpio.h> -#include <mach/wmt_iomux.h> -#include <linux/suspend.h> - -#include <mach/hardware.h> -#include <asm/dma.h> -#include "wmt-soc.h" -#include "wmt-pcm.h" - -#define NULL_DMA ((dmach_t)(-1)) -#define AUD_SPDIF_ENABLE 1 - -static int wmt_i2s_output = 0; //hdmi enable or not 2013-9-3 //maybe can remove it 2013-10-24 -static int wmt_codec_wm8994 = 0; //env set 2013-9-3 - -static int gpio_pa = -1; -static int gpio_active = 0; -extern int wmt_gpio_setpull(unsigned int gpio, enum wmt_gpio_pulltype pull); -/* - * Debug - */ -#define AUDIO_NAME "WMT_I2S" -//#define WMT_I2S_DEBUG 1 -//#define WMT_I2S_DEBUG_DETAIL 1 - -#ifdef WMT_I2S_DEBUG -#define DPRINTK(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -#else -#define DPRINTK(format, arg...) do {} while (0) -#endif - -#ifdef WMT_I2S_DEBUG_DETAIL -#define DBG_DETAIL(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": [%s]" format "\n" , __FUNCTION__, ## arg) -#else -#define DBG_DETAIL(format, arg...) do {} while (0) -#endif - -#define err(format, arg...) \ - printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) -#define info(format, arg...) \ - printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) -#define warn(format, arg...) \ - printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) - -struct wmt_i2s_asoc_data { - int stream_id; - unsigned int bus_id; - struct i2s_s i2s; - /* - * Flags indicating is the bus already activated and configured by - * another substream - */ - unsigned char HDMI_and_DAC0; //new env set to determine - unsigned char HDMI_aud_enable; //same with global wmt_i2s_output - - int active; - int configured; - unsigned char CH_SEL_NUM; - unsigned char HDMI_SPDIF_STATE; - /*struct timer_list delay_timer;*/ - struct audio_stream_a s[2]; -}; -static struct timer_list pa_timer; - -static int audio_interface_mode = 0;//add 2014-6-24 i2s left right - -static int wmt_pdm_module_enable = 0; -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); - -#define to_i2s_data(priv) container_of((priv), struct wmt_i2s_asoc_data, bus_id) -#define SNDRV_PCM_STREAM_ALL 2 - -static void i2s_init(int mode); -static void i2s_exit(void); - -#ifdef CONFIG_FB_WMT -extern int vpp_set_audio(int format, int sample_rate, int channel); -#endif - - -static struct wmt_i2s_asoc_data i2s_data[NUM_LINKS] = { - { - .bus_id = 0, //?? 2 SNDRV_PCM_STREAM_ALL - .i2s = { - /* interrupt counters */ - {0, 0, 0, 0, 0, 0, 0, 0}, - /* irq number*/ - 0, - /* reference counter */ - 0, - /* channels */ - 0, - /* format */ - 0, - /* fragment size */ - 0, - /* sample rate */ - 0, - i2s_init, - i2s_exit, - }, - .s = { - { - .id = "WMT I2S out", - .stream_id = SNDRV_PCM_STREAM_PLAYBACK, - .dmach = NULL_DMA, - .dma_dev = AHB1_AUD_DMA_REQ_1, - /*.dma_cfg = dma_device_cfg_table[I2S_TX_DMA_REQ],*/ - }, - { - .id = "WMT I2S in", - .stream_id = SNDRV_PCM_STREAM_CAPTURE, - .dmach = NULL_DMA, - .dma_dev = AHB1_AUD_DMA_REQ_0, - /*.dma_cfg = dma_device_cfg_table[I2S_RX_DMA_REQ],*/ - }, - }, - .HDMI_aud_enable = 0, - .HDMI_and_DAC0 = 0, - .CH_SEL_NUM = 2, - .HDMI_SPDIF_STATE = 6,//hdmi spdif play at sametime - }, -}; - - -/* for HDMI Audio status */ -int hd_audio_flag = 0; - - - -#ifdef CONFIG_WMT_I2S_INT -/* wmt_i2s_interrupt() - * - * It's only interrupt counter now, might be useful to - * debug or benchmark. - */ -static irqreturn_t -wmt_i2s_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - DBG_DETAIL(); - - return IRQ_HANDLED; -} -#endif - -#if 0 -static void delay_timer_handler(unsigned long data) -{ - DBG_DETAIL(); -} -#endif - -static void pa_timer_handler(unsigned long data) -{ - printk("%s\n", __func__); - if (gpio_pa >= 0) - { - - gpio_direction_output(gpio_pa, gpio_active); - } -} - -void wmt_i2s_ch_config(void) -{ - /* CH_SEL_NUM = 0, mesns output L to SPDIF&DAC's L and R - 1, mesns output R to SPDIF&DAC's L and R - 2, means normal stereo output to SPDIF&DAC */ - switch (i2s_data->CH_SEL_NUM) { - case 0: - ASMPFCHCFG0_VAL = 0x10100000; - ASMPF2HDACHCFG_VAL = 0x76543200; - break; - case 1: - ASMPFCHCFG0_VAL = 0x10101111; - ASMPF2HDACHCFG_VAL = 0x76543211; - break; - case 2: - ASMPFCHCFG0_VAL = 0x10101010; - ASMPF2HDACHCFG_VAL = 0x76543210; - break; - } - - if (i2s_data->i2s.channels == 0x01) { - ASMPFCHCFG0_VAL = 0x10100000; - ASMPF2HDACHCFG_VAL = 0x76543200; - } - - if (i2s_data->HDMI_aud_enable) { - /* disable DAC#0, if HDMI Audio is enabled */ - ASMPFCHCFG0_VAL &= 0xFFFF00FF; - ASMPFCHCFG0_VAL |= 0x00009800; - } - - /* HDMI_SPDIF_STATE = 3, means disable HDMI&SPDIF - 4, means enable HDMI only - 5, means enable SPDIF only - 6, means enable HDMI&SPDIF as normal */ - switch (i2s_data->HDMI_SPDIF_STATE) { - case 3: - ASMPFCHCFG0_VAL &= 0xFFFFFF00; - ASMPFCHCFG0_VAL |= 0x00000098; - ASMPF2HDACHCFG_VAL &= 0xFFFFFF00; - ASMPF2HDACHCFG_VAL |= 0x00000076; - break; - case 4: - ASMPFCHCFG0_VAL &= 0xFFFFFF00; - ASMPFCHCFG0_VAL |= 0x00000098; - break; - case 5: - ASMPF2HDACHCFG_VAL &= 0xFFFFFF00; - ASMPF2HDACHCFG_VAL |= 0x00000076; - break; - } -} - - -void wmt_i2s_dac0_ctrl(int HDMI_audio_enable) -{ - /* check if output to HDMI audio and DAC0 at same time */ - if (i2s_data->HDMI_and_DAC0) - return; - - if (HDMI_audio_enable) { - i2s_data->HDMI_aud_enable = 1; - info("HDMI Audio is enabled, disable dac0 of I2S"); - } - else { - i2s_data->HDMI_aud_enable = 0; - info("HDMI Audio is disabled, enable dac0 of I2S"); - } - - wmt_i2s_ch_config(); - - info("CHCFG0=0x%x, HDACHCFG=0x%x", ASMPFCHCFG0_VAL, ASMPF2HDACHCFG_VAL); -} -EXPORT_SYMBOL(wmt_i2s_dac0_ctrl); -void wmt_i2s_ch_sel(int ch_sel_num) -{ - if (ch_sel_num < 3) - i2s_data->CH_SEL_NUM = ch_sel_num; - else - i2s_data->HDMI_SPDIF_STATE = ch_sel_num; - - wmt_i2s_ch_config(); - - - info("SEL: CHCFG0=0x%x, HDACHCFG=0x%x", ASMPFCHCFG0_VAL, ASMPF2HDACHCFG_VAL); -} -EXPORT_SYMBOL(wmt_i2s_ch_sel); - -static void i2s_disable(void) -{ - DBG_DETAIL(); - - DACCFG_VAL &= ~DACITF_ENABLE; - ASMPFCFG_VAL &=~ASMPF_ENABLE; - HDACKGEN_VAL &= ~HDACKGEN_ENABLE; - -#ifdef AUD_SPDIF_ENABLE - DGOCFG_VAL &= ~DGOITF_ENABLE; -#endif - - AADCF0CFG_VAL &= ~(AADCITF_ENABLE | AADCF_ENABLE); -} - -static void i2s_enable(void) -{ - DBG_DETAIL(); - - AADCF0CFG_VAL |= (AADCITF_ENABLE | AADCF_ENABLE); - ASMPFCFG_VAL |= (ASMPF_ENABLE); - -#ifdef AUD_SPDIF_ENABLE - DGOCFG_VAL |= DGOITF_ENABLE; -#endif - - DACCFG_VAL |= DACITF_ENABLE; - - if (hd_audio_flag) - HDACKGEN_VAL |= HDACKGEN_ENABLE; -} - -static void aud_audprf_setting(unsigned char smp_rate_index) -{ - unsigned long cfg_tbl[] = {0x00002001, 0x00002001, 0x00002001, - 0x00002001, 0x00002001, 0x00002001, 0x00002001, 0x00002001, - 0x00002001, 0x00002001, 0x00002001, 0x00002001, - 0x00000001, 0x00000001, 0x00000001 - }; - unsigned int dgo_tbl[] = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00}; - unsigned int sysclk_tbl[] = {4096, 5632, 6144, 8192, 11264, 12288, 16384, - 22579, 24576, 32768, 45056, 49152, 16384, 22528, 24576}; -#ifdef AUD_SPDIF_ENABLE - unsigned int dgocs_tbl[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x02, 0x00, 0x08, 0x0A, 0x00, 0x0C, 0x0E}; -#endif - //unsigned int clock = 0; - unsigned long aud_reg_val; - - DBG_DETAIL(); - - ADCCFG_VAL = cfg_tbl[smp_rate_index]; - - aud_reg_val = dgo_tbl[smp_rate_index]; - DGOCFG_VAL = aud_reg_val; - HDACKGEN_VAL = aud_reg_val; - -#ifdef AUD_SPDIF_ENABLE - /* set ADGO channel status */ - aud_reg_val = dgocs_tbl[smp_rate_index] << 24; - DGOCS0A_VAL = aud_reg_val; - DGOCS1A_VAL = aud_reg_val; - //info("%s : DGOCS01A_VAL=0x%x", __func__, (unsigned int)aud_reg_val); -#endif - - DACCFG_VAL = cfg_tbl[smp_rate_index]; - - auto_pll_divisor(DEV_I2S, CLK_ENABLE , 0, 0); - auto_pll_divisor(DEV_I2S, SET_PLLDIV, 1, sysclk_tbl[smp_rate_index]); - /*clock = auto_pll_divisor(DEV_I2S, GET_FREQ , 0, 0); - info("%s : clock=%d", __func__, clock);*/ -} - -static unsigned char aud_smp_rate_convert(unsigned int smp_rate) -{ - unsigned char i = 0; - unsigned int smp_rate_tbl[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000, - 44100, 48000, 64000, 88200, 96000, 128000, 176000, 192000}; - - DBG_DETAIL(); - - /* boundary checking */ - if (smp_rate < 8000) { - i = 0x00; - } - else if (smp_rate > 192000) { - i = 0x0E; - } - else { - for (i = 0; i < 0x1F; i++) { - if (smp_rate == smp_rate_tbl[i]) { - break; - } - else if (smp_rate < smp_rate_tbl[i + 1]) { - if (smp_rate < (smp_rate_tbl[i] + ((smp_rate_tbl[i + 1] - smp_rate_tbl[i]) / 2))) { - break; - } - else { - i++; - break; - } - } - } - } - - return i; - -} - -static void i2s_sample_rate(unsigned int rate) -{ - unsigned char rate_index; - - DBG_DETAIL("rate=%d", rate); - - if (rate == i2s_data->i2s.rate) - return; - - i2s_data->i2s.rate = rate; - - rate_index = aud_smp_rate_convert(rate); - - aud_audprf_setting(rate_index); - -#ifdef CONFIG_FB_WMT - /* pass information of audio to HDMI Audio */ - hd_audio_flag = vpp_set_audio(16, rate, 2); -#endif -} - -static int i2sdacdat_gpio = -1;//means don't touch GP10 bit0-3 i2sDacDat0-3 - -void wmt_set_i2s_share_pin(void) -{ - int pwren_num,active_level,gpio_int_num; - char buf[256]; - int varlen = 256; - static int gpio26_mux = -1; - unsigned int gpval = 0x0; - - if(gpio26_mux == -1){ - if(wmt_getsyspara("wmt.bt.mtk6622",buf,&varlen) == 0) - { - sscanf(buf,"%d:%d:%d",&pwren_num,&active_level,&gpio_int_num); - printk("use customized value:p%d,a%d,i%d\n",pwren_num,active_level,gpio_int_num); - if(pwren_num == 62){ - gpio26_mux = 0x01; - }else{ - gpio26_mux = 0x00; - } - - }else{ - gpio26_mux = 0x00; - } - } - printk("%s gpio26_mux:%d\n",__func__,gpio26_mux); - if(!gpio26_mux){ - /* disable GPIO and enable Pull Down mode */ - gpval &= ~0xff; - //GPIO_CTRL_GP10_I2S_BYTE_VAL &= ~0xFF; // 0xFF bit1 - }else{ - gpval &= ~0xF7; - //GPIO_CTRL_GP10_I2S_BYTE_VAL &= ~0xF7; - } - - // configure I2SDACDAT1/2/3 as GPIO function but mmax-wm8994 that configured as I2SADCLRC/I2SADCBLCK - if (!wmt_codec_wm8994) - { - gpval |= (BIT1 | BIT2 | BIT3); - //GPIO_CTRL_GP10_I2S_BYTE_VAL |= (BIT1 | BIT2 | BIT3); - - } - - //add for mainly i2sdacdat1 work as gpio to control led 2014-8-15 so here just keep it specific func - //tp driver will use it as gpio - switch (i2sdacdat_gpio) - { - case 1: - gpval |= BIT1; - //GPIO_CTRL_GP10_I2S_BYTE_VAL |= BIT1; // i2sdacdat1 work as gpio - break; - case 2: - gpval |= BIT2; - //GPIO_CTRL_GP10_I2S_BYTE_VAL |= BIT2; - break; - case 3: - gpval |= BIT3; - //GPIO_CTRL_GP10_I2S_BYTE_VAL |= BIT3; - break; - - } - GPIO_CTRL_GP10_I2S_BYTE_VAL = gpval; - - GPIO_CTRL_GP11_I2S_BYTE_VAL &= ~(BIT0 | BIT1 | BIT2); - - if(!gpio26_mux){ - PULL_EN_GP10_I2S_BYTE_VAL |= 0xFF; - }else{ - PULL_EN_GP10_I2S_BYTE_VAL |= 0xF7; - } - PULL_EN_GP11_I2S_BYTE_VAL |= (BIT0 | BIT1 | BIT2); - - if(!gpio26_mux){ - /* set to 2ch input, 2ch output */ - PIN_SHARING_SEL_4BYTE_VAL &= ~(BIT15 | BIT17 | BIT19 | BIT20); - PIN_SHARING_SEL_4BYTE_VAL |= (BIT1 | BIT16 | BIT18); - }else{ - PIN_SHARING_SEL_4BYTE_VAL &= ~(BIT15 | BIT17 | BIT20); - PIN_SHARING_SEL_4BYTE_VAL |= (BIT1 | BIT16); - } -} -EXPORT_SYMBOL(wmt_set_i2s_share_pin); - -static void i2s_init(int mode) -{ -#ifdef DEBUG - int ret; -#endif - int temp ; - //unsigned int clock = 0; - - DPRINTK("i2s_ref = %d ", i2s_data->i2s.ref); - - if (++i2s_data->i2s.ref > 1) - return; - - DBG_DETAIL(); - - if (!mode) { - /* set to 24.576MHz */ - auto_pll_divisor(DEV_I2S, CLK_ENABLE , 0, 0); - auto_pll_divisor(DEV_I2S, SET_PLLDIV, 1, 24576); - /*clock = auto_pll_divisor(DEV_I2S, GET_FREQ , 0, 0); - info("%s : clock=%d \n" , __func__, clock);*/ - - /* Enable BIT4:ARFP clock, BIT3:ARF clock */ - PMCEU_VAL |= (BIT4 | BIT3); - - /* Enable BIT2:AUD clock */ - PMCE3_VAL |= BIT2; - - wmt_set_i2s_share_pin(); - } - - /* connect DZDRQ8 to ADC0 FIFO, DZDRQ9 to DAC FIFO and DZDRQA to ADC1 FIFO */ - DZDRQ8_CFG_VAL = 0x0; - DZDRQ9_CFG_VAL = 0x1; - DZDRQA_CFG_VAL = 0x2; - - DACCFG_VAL = 0x0; - ADCCFG_VAL = 0x0; - - /* little endian, signed format, enable sample FIFO, 16bit sample, 2 channel */ - ASMPFCFG_VAL = 0x52; - - /* assign ch0 to DAC#0_L, DAC#1_L, DAC#2_L, SPDIF_L, - ch1 to DAC#0_R, DAC#1_R, DAC#2_R, SPDIF_R */ - ASMPFCHCFG0_VAL = 0x10101010; - - /* assign ch0 to DAC#3_L, ch1 to DAC#3_R */ - ASMPFCHCFG1_VAL = 0x10; - - /* select ADCDAT0, 16 bits mode, enable AADCFIFO and AADCITF */ - AADCF0CFG_VAL = (AADCITF_ENABLE | AADCF16_ENABLE | AADCF_ENABLE); - - /* the sequence must be ARF_ADCCFG first then ARF_DGOCFG, finally ARF_DACCFG while slave mode, - otherwise will generate noise when record function is active */ - - /* ADC slave mode, 48K sample rate, I2S mode */ - ADCCFG_VAL = 0x2001; - - i2s_data->i2s.rate = 48000; - i2s_data->i2s.channels = 2; - i2s_data->i2s.format = SNDRV_PCM_FORMAT_S16_LE; - -#ifdef AUD_SPDIF_ENABLE - /* B1: 0 -> PCM, 1 -> Bitstream - B24 ~ B27: sample rate */ - /* set ADGO channel status for 48K sample rate */ - DGOCS0A_VAL = 0x02 << 24; - DGOCS1A_VAL = 0x02 << 24; - - /* enable ADGOITF and ADGOCKGEN for 48K sample rate */ - DGOCFG_VAL = 0x82; -#endif - - /* enable ADACITF and ADACCKGEN for 44.1K sample rate, I2S mode */ - DACCFG_VAL = 0x402001; - if (audio_interface_mode == 1) - { - printk("<<<<<%s left justified!\n", __func__); - //left justified bit20: 0->i2s, 1->l/r clock polarity - DACCFG_VAL |= 0x1 << 20; - //bit7:0 padding added to dac serial data output - //0 = LJ - //1 = I2S - //others = RJ (depends on Bit 11:8) - - DACCFG_VAL &= ~(0x1<<0); - - } - - /* enable HD Audio clock for 48K sample rate or not*/ - HDACKGEN_VAL = 0x12; - -#ifdef CONFIG_FB_WMT - /* pass information of audio to HDMI Audio */ - hd_audio_flag = vpp_set_audio(16, i2s_data->i2s.rate, i2s_data->i2s.channels); - ASMPF2HDACHCFG_VAL = 0x76543210; -#endif - - if (!hd_audio_flag) - HDACKGEN_VAL = 0; - - /* audio peri reset */ - temp = AUDPRFRST_VAL; - -#ifdef AUD_SPDIF_ENABLE - temp |= (ASMPF_RESET | DACITF_RESET | ADCITF_RESET | DGOITF_RESET); -#else - temp |= (ASMPF_RESET | DACITF_RESET | ADCITF_RESET); -#endif - - AUDPRFRST_VAL = temp; - - /* - request irq - */ -#ifdef CONFIG_WMT_I2S_INT - ret = request_irq(i2s_data->i2s.irq, - wmt_i2s_interrupt, - SA_INTERRUPT, - "wmt_alsa_vt1602", - NULL); - if (ret) - printk("%s : unable to request IRQ \n" , __func__); -#endif -} - -static void i2s_exit(void) -{ - DBG_DETAIL(); - - if (--i2s_data->i2s.ref) - return; - - DPRINTK("Do i2s_exit "); - -#ifdef CONFIG_WMT_I2S_INT - free_irq(i2s_data->i2s.irq, NULL); -#endif - - /* Reset counter.*/ - memset(&i2s_data->i2s.ints, 0, sizeof(struct i2s_ints_s)); - return; -} - -static int wmt_i2s_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int stream_id = substream->pstr->stream; - struct audio_stream_a *s = &i2s_data->s[0]; - - DBG_DETAIL(); - - s[stream_id].stream = substream; - - runtime->private_data = s; - - return 0; -} - -static void wmt_i2s_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) -{ - DBG_DETAIL(); -} - -static int wmt_i2s_dai_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - int err = 0; - int stream_id = substream->pstr->stream; - - DBG_DETAIL(); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { - ASMPFCFG_VAL |= ASMPF_ENABLE; - } - else if (stream_id == SNDRV_PCM_STREAM_CAPTURE) { - AADCF0CFG_VAL |= AADCF_ENABLE; - } - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { - ASMPFCFG_VAL &= ~ASMPF_ENABLE; - } - else if (stream_id == SNDRV_PCM_STREAM_CAPTURE) { - AADCF0CFG_VAL &= ~AADCF_ENABLE; - } - - /* - mod_timer(&i2s_data->delay_timer, jiffies + HZ / 100); - */ - break; - default: - err = -EINVAL; - } - - return err; -} - -static int wmt_i2s_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -{ - DBG_DETAIL(); - return 0; -} - -static int wmt_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int channel, byte; - int stream_id = substream->pstr->stream; - -#ifdef CONFIG_SND_OSSEMUL - //info("oss.rate=%d, oss.channels=%d", runtime->oss.rate, runtime->oss.channels); -#else - DBG_DETAIL(); -#endif - - byte = (runtime->sample_bits)/8; - channel = runtime->channels; - - DPRINTK("snd_wmt_alsa_prepare byte = %d, channels = %d", byte, runtime->channels); - - - if ((runtime->rate != i2s_data->i2s.rate) || (runtime->format != i2s_data->i2s.format) || - (runtime->channels != i2s_data->i2s.channels) || (stream_id != i2s_data->stream_id)) { - info("*** stream_id=%d, rate=%d, format=0x%x channels=%d ***", - stream_id, runtime->rate, runtime->format, runtime->channels); - i2s_data->i2s.format = runtime->format; - i2s_data->i2s.channels = runtime->channels; - i2s_data->stream_id = stream_id; - } - else { - return 0; - } - - i2s_disable(); - - /* format setting */ - if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) { - /* little or big endian check */ - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S16_BE: - case SNDRV_PCM_FORMAT_U16_BE: - case SNDRV_PCM_FORMAT_S24_BE: - case SNDRV_PCM_FORMAT_U24_BE: - case SNDRV_PCM_FORMAT_S32_BE: - case SNDRV_PCM_FORMAT_U32_BE: - ASMPFCFG_VAL |= ASMPF_EXCH_ENDIAN; - break; - default: - ASMPFCFG_VAL &= ~ASMPF_EXCH_ENDIAN; - break; - } - - /* unsigned or signed check */ - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U8: - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_U16_BE: - case SNDRV_PCM_FORMAT_U24_LE: - case SNDRV_PCM_FORMAT_U24_BE: - case SNDRV_PCM_FORMAT_U32_LE: - case SNDRV_PCM_FORMAT_U32_BE: - ASMPFCFG_VAL |= ASMPF_EXCH_FMT; - break; - default: - ASMPFCFG_VAL &= ~ASMPF_EXCH_FMT; - break; - } - - /* sample quantization check */ - ASMPFCFG_VAL &= ~(BIT4 | BIT5); - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S8: - case SNDRV_PCM_FORMAT_U8: - ASMPFCFG_VAL |= ASMPF_8BIT_SMP; - break; - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_U16_BE: - ASMPFCFG_VAL |= ASMPF_16BIT_SMP; - break; - case SNDRV_PCM_FORMAT_S32_LE: - case SNDRV_PCM_FORMAT_S32_BE: - case SNDRV_PCM_FORMAT_U32_LE: - case SNDRV_PCM_FORMAT_U32_BE: - ASMPFCFG_VAL |= ASMPF_32BIT_SMP; - break; - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S24_BE: - case SNDRV_PCM_FORMAT_U24_LE: - case SNDRV_PCM_FORMAT_U24_BE: - info("*** Not Supported: fmt=24Bit ***"); - default: - break; - } - - /* channel number check */ - ASMPFCFG_VAL &= ~(BIT0 | BIT1 | BIT2 | BIT3); - ASMPFCFG_VAL |= runtime->channels; - - wmt_i2s_ch_config(); - info("Prepare: CHCFG0=0x%x, HDACHCFG=0x%x", ASMPFCHCFG0_VAL, ASMPF2HDACHCFG_VAL); - } - - /* sample rate setting */ -#ifdef CONFIG_SND_OSSEMUL - if (runtime->oss.rate) { - i2s_sample_rate(runtime->oss.rate); - } - else { - i2s_sample_rate(runtime->rate); - } -#else - i2s_sample_rate(runtime->rate); -#endif - - i2s_enable(); - - /* - printk("avail_max=%d, rate=%d, channels=%d, period_size=%d, periods=%d, buffer_size=%d, tick_time=%d, \ - min_align=%d, byte_align=%d, frame_bits=%d, sample_bits=%d, sleep_min=%d, xfer_align=%d, boundary=%d\n", - runtime->avail_max, runtime->rate, runtime->channels, runtime->period_size, runtime->periods, - runtime->buffer_size, runtime->tick_time, runtime->min_align, runtime->byte_align, - runtime->frame_bits, runtime->sample_bits, - runtime->sleep_min, runtime->xfer_align, runtime->boundary); - */ - return 0; -} - -/* - * This must be called before _set_clkdiv and _set_sysclk since McBSP register - * cache is initialized here - */ -static int wmt_i2s_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - DBG_DETAIL(); - return 0; //add rambo 2013-3-13 - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - break; - default: - /* Unsupported data format */ - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - break; - case SND_SOC_DAIFMT_CBM_CFM: - break; - default: - return -EINVAL; - } - - /* Set bit clock (CLKX/CLKR) and FS polarities */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - /* - * Normal BCLK + FS. - * FS active low. TX data driven on falling edge of bit clock - * and RX data sampled on rising edge of bit clock. - */ - break; - case SND_SOC_DAIFMT_NB_IF: - break; - case SND_SOC_DAIFMT_IB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - break; - default: - return -EINVAL; - } - - return 0; -} - -#ifdef CONFIG_PM -static int wmt_i2s_suspend(struct snd_soc_dai *cpu_dai) -{ - printk("%s!\n", __func__); - - DBG_DETAIL(); - - i2s_data->i2s.ref = 0; -#if 1 - if (gpio_pa >= 0) - { - gpio_direction_output(gpio_pa, !gpio_active); - } -#endif - return 0; -} - -static int wmt_i2s_resume(struct snd_soc_dai *cpu_dai) -{ - printk("%s!\n", __func__); - - DBG_DETAIL(); - - i2s_init(1); - - wmt_i2s_ch_config(); -#if 1 - if (gpio_pa >= 0) - { - gpio_direction_output(gpio_pa, gpio_active); - mdelay(50); - } -#endif - info("Resume: CHCFG0=0x%x, HDACHCFG=0x%x", ASMPFCHCFG0_VAL, ASMPF2HDACHCFG_VAL); - return 0; -} -#else -#define wmt_i2s_suspend NULL -#define wmt_i2s_resume NULL -#endif - -static struct snd_soc_dai_ops wmt_i2s_dai_ops = { - .startup = wmt_i2s_dai_startup, - .prepare = wmt_i2s_prepare, - .shutdown = wmt_i2s_dai_shutdown, - .trigger = wmt_i2s_dai_trigger, - .hw_params = wmt_i2s_dai_hw_params, - .set_fmt = wmt_i2s_dai_set_dai_fmt, -}; - -struct snd_soc_dai_driver wmt_i2s_dai = { - .suspend = wmt_i2s_suspend, - .resume = wmt_i2s_resume, - .playback = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_FLOAT, - }, - .capture = { - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &wmt_i2s_dai_ops, -}; - -static int wmt_i2s_probe(struct platform_device *pdev) -{ - int ret; - char buf[64]; - int varlen = 64; - - DBG_DETAIL(); - - ret = wmt_getsyspara("wmt.audio.pcm", buf, &varlen); - if (ret == 0) { - sscanf(buf, "%d", &wmt_pdm_module_enable); - } - - ret = wmt_getsyspara("wmt.audio.i2s", buf, &varlen); - if (ret == 0) { - if (!strncmp(buf, "wm8994", strlen("wm8994"))) - wmt_codec_wm8994 = 1; - } - memset(buf, 0, sizeof(buf)); - ret = wmt_getsyspara("wmt.audio.codechdmi", buf, &varlen); - if (ret == 0) { - sscanf(buf, "%d", &i2s_data[0].HDMI_and_DAC0); - printk("<<<%s codec and hdmi:%d\n", __FUNCTION__, i2s_data[0].HDMI_and_DAC0); - } - - memset(buf, 0, sizeof(buf)); - //0:i2sdacdat0(usually use i2s function!!) 1:i2sdacdat1 2:i2sdacdat2 3:i2sdacdat3 - ret = wmt_getsyspara("wmt.audio.dacdat.gpio", buf, &varlen); - if (ret == 0) { - sscanf(buf, "%d", &i2sdacdat_gpio); - printk("<<<%s i2sdacdat_gpio:%d\n", __FUNCTION__, i2sdacdat_gpio); - } - - - memset(buf, 0, sizeof(buf)); - ret = wmt_getsyspara("wmt.audio.interface.mode", buf, &varlen); - if (ret == 0) { // 0:i2s 1:left justified 2:right justified - sscanf(buf, "%d", &audio_interface_mode); - printk("<<<%s audio_interface_mode:%d\n", __FUNCTION__, audio_interface_mode); - } - - memset(buf, 0, sizeof(buf)); - ret = wmt_getsyspara("wmt.audio.pa", buf, &varlen); - if (ret == 0) { // gpio nr:active---> 1:0 - sscanf(buf, "%d:%d", &gpio_pa, &gpio_active); - - } - printk("%s audio pa:%d:%d\n", __FUNCTION__, gpio_pa, gpio_active); - if (gpio_pa >= 0) - { - ret = gpio_request(gpio_pa, "audio pa"); - if (ret) - { - printk("%s gpio %d request error!\n", __func__, gpio_pa); - return ret; - } - #if 0 - if (gpio_active) - wmt_gpio_setpull(gpio_pa, WMT_GPIO_PULL_DOWN); - else - wmt_gpio_setpull(gpio_pa, WMT_GPIO_PULL_UP); - msleep(10); - gpio_direction_output(gpio_pa, !gpio_active); //???pop??? - printk("%s shutdown pa!\n", __func__); - msleep(100); - #endif - - - init_timer(&pa_timer); - pa_timer.function = pa_timer_handler; - } - i2s_data->s[0].dma_cfg = dma_device_cfg_table[AHB1_AUD_DMA_REQ_1]; - i2s_data->s[1].dma_cfg = dma_device_cfg_table[AHB1_AUD_DMA_REQ_0]; - /*init i2s controller*/ - i2s_data->i2s.init(0); - - spin_lock_init(&i2s_data->s[0].dma_lock); - spin_lock_init(&i2s_data->s[1].dma_lock); - /*init_timer(&i2s_data->delay_timer); - i2s_data->delay_timer.function = delay_timer_handler;*/ - - /* register with the ASoC layers */ - ret = snd_soc_register_dai(&pdev->dev, &wmt_i2s_dai); - if (ret) { - pr_err("Failed to register DAI: %d\n", ret); - return ret; - } - - if (gpio_pa >= 0) - { - mod_timer(&pa_timer, jiffies+msecs_to_jiffies(10000)); - } - return 0; -} - -static int __devexit wmt_i2s_remove(struct platform_device *pdev) -{ - DBG_DETAIL(); - - snd_soc_unregister_dai(&pdev->dev); - - return 0; -} - -static void wmt_i2s_plat_shutdown(struct platform_device *pdev) -{ - printk("%s!\n", __func__); - if (gpio_pa >= 0) - { - gpio_direction_output(gpio_pa, !gpio_active); - } -} - -static struct platform_driver wmt_i2s_driver = { - .probe = wmt_i2s_probe, - .remove = __devexit_p(wmt_i2s_remove), - //.suspend = wmt_i2s_plat_suspend, - //.resume = wmt_i2s_plat_resume, - .shutdown = wmt_i2s_plat_shutdown, - .driver = { - .name = "wmt-i2s", - .owner = THIS_MODULE, - }, -}; - - -static int __init wmt_i2s_init(void) -{ - DBG_DETAIL(); - - return platform_driver_register(&wmt_i2s_driver); -} - -static void __exit wmt_i2s_exit(void) -{ - DBG_DETAIL(); - - platform_driver_unregister(&wmt_i2s_driver); -} - -module_init(wmt_i2s_init); -module_exit(wmt_i2s_exit); - -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_DESCRIPTION("WMT [ALSA SoC] driver"); -MODULE_LICENSE("GPL"); - |