static int tegra_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct tegra_audio_data* audio_data = rtd->socdev->codec_data; enum dac_dap_data_format data_fmt; int dai_flag = 0, sys_clk; int err; ASOC_FUNCTION(""); if (tegra_das_is_port_master(tegra_audio_codec_type_bluetooth)) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_bluetooth); /* We are supporting DSP and I2s format for now */ if (data_fmt & dac_dap_data_format_dsp) dai_flag |= SND_SOC_DAIFMT_DSP_A; else dai_flag |= SND_SOC_DAIFMT_I2S; err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { pr_err("codec_dai fmt not set \n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { pr_err("cpu_dai fmt not set \n"); return err; } sys_clk = clk_get_rate(audio_data->dap_mclk); err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } return 0; }
static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; int dai_flag = 0, sys_clk; int err; enum dac_dap_data_format data_fmt; /* Program the cpu_dai only */ data_fmt = dac_dap_data_format_i2s; #ifdef CONFIG_ARCH_TEGRA_2x_SOC data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_hifi); if (tegra_das_is_port_master(tegra_audio_codec_type_hifi)) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; else #endif dai_flag |= SND_SOC_DAIFMT_CBS_CFS; if ((data_fmt & dac_dap_data_format_tdm)) dai_flag |= SND_SOC_DAIFMT_DSP_A; else if ((data_fmt & dac_dap_data_format_rjm)) dai_flag |= SND_SOC_DAIFMT_RIGHT_J; else if ((data_fmt & dac_dap_data_format_i2s)) dai_flag |= SND_SOC_DAIFMT_I2S; else if ((data_fmt & dac_dap_data_format_ljm)) dai_flag |= SND_SOC_DAIFMT_LEFT_J; err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { pr_err("cpu_dai fmt not set\n"); return err; } sys_clk = 48000 * 512; err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } return 0; }
static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_codec *codec = codec_dai->codec; struct tegra_audio_data* audio_data = rtd->socdev->codec_data; enum dac_dap_data_format data_fmt; int dai_flag = 0, sys_clk; int err; ASOC_FUNCTION(""); if (tegra_das_is_port_master(tegra_audio_codec_type_hifi)) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_hifi); /* We are supporting DSP and I2s format for now */ if (data_fmt & dac_dap_data_format_i2s) dai_flag |= SND_SOC_DAIFMT_I2S; else dai_flag |= SND_SOC_DAIFMT_DSP_A; err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { pr_err("codec_dai fmt not set \n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { pr_err("cpu_dai fmt not set \n"); return err; } sys_clk = clk_get_rate(audio_data->dap_mclk); err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("codec_dai clock not set\n"); return err; } err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) { int CtrlReg = 0; int VolumeCtrlReg = 0; int SidetoneCtrlReg = 0; int SideToneAtenuation = 0; snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, 0X7); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, 0X7); /* Mic Bias enable */ CtrlReg = (0x1<<B00_MICBIAS_ENA) | (0x1<<B01_MICDET_ENA); snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, CtrlReg); /* Enable DRC */ CtrlReg = snd_soc_read(codec, WM8903_DRC_0); CtrlReg |= (1<<B15_DRC_ENA); snd_soc_write(codec, WM8903_DRC_0, CtrlReg); CtrlReg = LUNA_INTERNAL_MIC_SETTING_R1R2; snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_1, CtrlReg); CtrlReg = LUNA_EXTERNAL_MIC_SETTING_L2L1; snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_1, CtrlReg); VolumeCtrlReg = (0x1C << B00_IN_VOL); /* Mic Setting */ snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, VolumeCtrlReg); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, VolumeCtrlReg); CtrlReg = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_0); CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCR, 0x0); CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B07_AIF_ADCL, 0x0); snd_soc_write(codec, WM8903_AUDIO_INTERFACE_0, CtrlReg); /* Enable analog inputs */ CtrlReg = (0x1<<B01_INL_ENA) | (0x1<<B00_INR_ENA); snd_soc_write(codec, WM8903_POWER_MANAGEMENT_0, CtrlReg); /* ADC Settings */ CtrlReg = snd_soc_read(codec, WM8903_ADC_DIGITAL_0); CtrlReg |= (0x1<<B04_ADC_HPF_ENA); snd_soc_write(codec, WM8903_ADC_DIGITAL_0, CtrlReg); #if 0 SidetoneCtrlReg = 0; snd_soc_write(codec, R20_SIDETONE_CTRL, SidetoneCtrlReg); #endif /* Enable ADC */ CtrlReg = snd_soc_read(codec, WM8903_POWER_MANAGEMENT_6); CtrlReg |= (0x1<<B00_ADCR_ENA)|(0x1<<B01_ADCL_ENA); snd_soc_write(codec, WM8903_POWER_MANAGEMENT_6, CtrlReg); #if 0 SidetoneCtrlReg = (0x1<<2) | (0x2<<0); SideToneAtenuation = 12 ; SidetoneCtrlReg |= (SideToneAtenuation<<8) | (SideToneAtenuation<<4); snd_soc_write(codec, R20_SIDETONE_CTRL, SidetoneCtrlReg); #endif CtrlReg = snd_soc_read(codec, R29_DRC_1); CtrlReg |= 0x3; /*mic volume 18 db */ snd_soc_write(codec, R29_DRC_1, CtrlReg); } return 0; }
static int tegra_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card* card = codec->card; struct tegra_alc5623* machine = snd_soc_card_get_drvdata(card); int sys_clk; int err; #ifdef USE_ORG_DAS /* Get DAS dataformat and master flag */ int codec_is_master = !tegra_das_is_port_master(tegra_audio_codec_type_bluetooth); enum dac_dap_data_format data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_bluetooth); /* We are supporting DSP and I2s format for now */ int dai_flag = 0; if (data_fmt & dac_dap_data_format_dsp) dai_flag |= SND_SOC_DAIFMT_DSP_A; else dai_flag |= SND_SOC_DAIFMT_I2S; if (codec_is_master) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; /* codec is master */ else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; #else /* Get DAS dataformat and master flag */ int codec_is_master = machine->bt_codec_master; /* We are supporting DSP and I2s format for now */ int dai_flag = machine->bt_codec_datafmt; if (codec_is_master) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; /* codec is master */ else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; #endif dev_dbg(card->dev,"%s(): format: 0x%08x, channels:%d, srate:%d\n", __FUNCTION__, params_format(params),params_channels(params),params_rate(params)); /* Set the CPU dai format. This will also set the clock rate in master mode */ err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { dev_err(card->dev,"cpu_dai fmt not set \n"); return err; } /* Bluetooth Codec is always slave here */ err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { dev_err(card->dev,"codec_dai fmt not set \n"); return err; } /* Get system clock */ sys_clk = clk_get_rate(machine->util_data.clk_cdev1); /* Set CPU sysclock as the same - in Tegra, seems to be a NOP */ err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev,"cpu_dai clock not set\n"); return err; } /* Set CODEC sysclk */ err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev,"cpu_dai clock not set\n"); return err; } return 0; }
static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card* card = codec->card; struct tegra_alc5623* machine = snd_soc_card_get_drvdata(card); int sys_clk; int err; int i; /* Get the requested sampling rate */ unsigned int srate = params_rate(params); #ifdef USE_ORG_DAS /* I2S <-> DAC <-> DAS <-> DAP <-> CODEC -If DAP is master, codec will be slave */ int codec_is_master = !tegra_das_is_port_master(tegra_audio_codec_type_hifi); /* Get DAS dataformat - DAP is connecting to codec */ enum dac_dap_data_format data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_hifi); /* We are supporting DSP and I2s format for now */ int dai_flag = 0; if (data_fmt & dac_dap_data_format_i2s) dai_flag |= SND_SOC_DAIFMT_I2S; else dai_flag |= SND_SOC_DAIFMT_DSP_A; if (codec_is_master) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; /* codec is master */ else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; #else /* I2S <-> DAC <-> DAS <-> DAP <-> CODEC -If DAP is master, codec will be slave */ bool codec_is_master = machine->hifi_codec_master; /* Get DAS dataformat - DAP is connecting to codec */ int dai_flag = machine->hifi_codec_datafmt; /* Depending on the number of channels, we must select the mode - I2S only supports stereo operation, DSP_A can support mono with the ALC5624 */ /*t dai_flag = (params_channels(params) == 1) ? SND_SOC_DAIFMT_DSP_A : SND_SOC_DAIFMT_I2S;*/ dev_dbg(card->dev,"%s(): cpu_dai:'%s'\n", __FUNCTION__,cpu_dai->name); dev_dbg(card->dev,"%s(): codec_dai:'%s'\n", __FUNCTION__,codec_dai->name); if (codec_is_master) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; /* codec is master */ else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; #endif dev_dbg(card->dev,"%s(): format: 0x%08x, channels:%d, srate:%d\n", __FUNCTION__, params_format(params),params_channels(params),params_rate(params)); /* Set the CPU dai format. This will also set the clock rate in master mode */ err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { dev_err(card->dev,"cpu_dai fmt not set \n"); return err; } err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { dev_err(card->dev,"codec_dai fmt not set \n"); return err; } /* Get system clock */ sys_clk = clk_get_rate(machine->util_data.clk_cdev1); if (codec_is_master) { dev_dbg(card->dev,"%s(): codec in master mode\n",__FUNCTION__); /* If using port as slave (=codec as master), then we can use the codec PLL to get the other sampling rates */ /* Try each one until success */ for (i = 0; i < ARRAY_SIZE(clocktab); i++) { if (clocktab[i].srate != srate) continue; if (snd_soc_dai_set_pll(codec_dai, 0, 0, sys_clk, clocktab[i].mclk) >= 0) { /* Codec PLL is synthetizing this new clock */ sys_clk = clocktab[i].mclk; break; } } if (i >= ARRAY_SIZE(clocktab)) { dev_err(card->dev,"%s(): unable to set required MCLK for SYSCLK of %d, sampling rate: %d\n",__FUNCTION__,sys_clk,srate); return -EINVAL; } } else { dev_dbg(card->dev,"%s(): codec in slave mode\n",__FUNCTION__); /* Disable codec PLL */ err = snd_soc_dai_set_pll(codec_dai, 0, 0, sys_clk, sys_clk); if (err < 0) { dev_err(card->dev,"%s(): unable to disable codec PLL\n",__FUNCTION__); return err; } /* Check this sampling rate can be achieved with this sysclk */ for (i = 0; i < ARRAY_SIZE(clocktab); i++) { if (clocktab[i].srate != srate) continue; if (sys_clk == clocktab[i].mclk) break; } if (i >= ARRAY_SIZE(clocktab)) { dev_err(card->dev,"%s(): unable to get required %d hz sampling rate of %d hz SYSCLK\n",__FUNCTION__,srate,sys_clk); return -EINVAL; } } err = tegra_asoc_utils_set_rate(&machine->util_data, srate, sys_clk); if (err < 0) { dev_err(card->dev, "Can't configure clocks\n"); return err; } /* Set CODEC sysclk */ err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev,"codec_dai clock not set\n"); return err; } return 0; }
static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_codec *codec = codec_dai->codec; struct tegra_audio_data* audio_data = rtd->socdev->codec_data; enum dac_dap_data_format data_fmt; int dai_flag = 0, sys_clk; int err; int hs_type; int CtrlReg = 0; if (tegra_das_is_port_master(tegra_audio_codec_type_hifi)) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_hifi); /* We are supporting DSP and I2s format for now */ if (data_fmt & dac_dap_data_format_i2s) dai_flag |= SND_SOC_DAIFMT_I2S; else dai_flag |= SND_SOC_DAIFMT_DSP_A; err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { pr_err("codec_dai fmt not set \n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { pr_err("cpu_dai fmt not set \n"); return err; } sys_clk = clk_get_rate(audio_data->dap_mclk); err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("codec_dai clock not set\n"); return err; } err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) { int VolumeCtrlReg = 0; hs_type = check_hs_type(); if(jack_alive && hs_type){ printk("Headset connected, enable external Mic(AMIC)\n"); /* Disable Digital Microphone(DMIC) for audio input function */ CtrlReg = (0x0 << B08_GPIO_FN) |(0x1 << B07_GPIO_DIR) |(0x1 << B05_GPIO_IP_CFG) |(0x1 << B03_GPIO_PD); snd_soc_write(codec, R74_GPIO_CTRL_1, CtrlReg); /*0x00A8*/ CtrlReg = (0x0 << B08_GPIO_FN) |(0x1 << B07_GPIO_DIR) |(0x1 << B05_GPIO_IP_CFG) |(0x1 << B03_GPIO_PD); snd_soc_write(codec, R75_GPIO_CTRL_2, CtrlReg); /*0x00A8*/ CtrlReg = (0x0 << B09_DIGMIC); snd_soc_write(codec, RA4_ADC_DIG_MIC, CtrlReg);/*0x0000*/ snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, 0X7); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, 0X7); // Mic Bias enable CtrlReg = (0x1<<B00_MICBIAS_ENA) | (0x1<<B01_MICDET_ENA); snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, CtrlReg); // Enable DRC CtrlReg = snd_soc_read(codec, WM8903_DRC_0); CtrlReg |= (1<<B15_DRC_ENA); snd_soc_write(codec, WM8903_DRC_0, CtrlReg); // Single Ended Mic CtrlReg = (0x0<<B06_IN_CM_ENA) | (0x0<<B00_MODE) | (0x0<<B04_IP_SEL_N) | (0x1<<B02_IP_SEL_P); VolumeCtrlReg = (audio_params[EP101].analog_headset_mic_volume << B00_IN_VOL); // Mic Setting snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_1, CtrlReg); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_1, CtrlReg); // voulme for single ended mic snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, VolumeCtrlReg); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, VolumeCtrlReg); /* Left ADC data on both channels */ CtrlReg = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_0); CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCR, 0x0); CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCL, 0x0); snd_soc_write(codec, WM8903_AUDIO_INTERFACE_0, CtrlReg); }else{ printk("Headset disconnected, enable internal Mic(DMIC)\n"); /* Enable Digital Microphone(DMIC) for audio input function */ CtrlReg = (0x1 << B06_AIFADCR_SRC) |(0x1 << B04_AIFDACR_SRC); snd_soc_write(codec, WM8903_AUDIO_INTERFACE_0, CtrlReg); /*0x0050*/ CtrlReg = (0x6 << B08_GPIO_FN) |(0x0 << B07_GPIO_DIR) |(0x1 << B05_GPIO_IP_CFG) |(0x1 << B03_GPIO_PD); snd_soc_write(codec, WM8903_GPIO_CONTROL_1, CtrlReg); /*0x0628*/ CtrlReg = (0x6 << B08_GPIO_FN) |(0x1 << B07_GPIO_DIR) |(0x1 << B05_GPIO_IP_CFG) |(0x1 << B03_GPIO_PD); snd_soc_write(codec, WM8903_GPIO_CONTROL_2, CtrlReg); /*0x06A8*/ CtrlReg = (0x1 << B09_DIGMIC); snd_soc_write(codec, WM8903_CLOCK_RATE_TEST_4, CtrlReg);/*0x2A38*/ snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, audio_params[EP101].analog_DMIC_ADC_volume | 0x100); /* ADC Digital volume left: 17.625dB*/ snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, audio_params[EP101].analog_DMIC_ADC_volume | 0x100); /* ADC Digital volume right: 17.625dB*/ } //-------------------------------------- // Enable analog inputs CtrlReg = (0x1<<B01_INL_ENA); snd_soc_write(codec, WM8903_POWER_MANAGEMENT_0, CtrlReg); // ADC Settings CtrlReg = snd_soc_read(codec, WM8903_ADC_DIGITAL_0); CtrlReg |= (0x1<<B04_ADC_HPF_ENA); snd_soc_write(codec, WM8903_ADC_DIGITAL_0, CtrlReg); /* Disable sidetone */ CtrlReg = 0; snd_soc_write(codec, R20_SIDETONE_CTRL, CtrlReg); // Enable ADC CtrlReg = snd_soc_read(codec, WM8903_POWER_MANAGEMENT_6); CtrlReg |= (0x1<<B01_ADCL_ENA); snd_soc_write(codec, WM8903_POWER_MANAGEMENT_6, CtrlReg); CtrlReg = snd_soc_read(codec, R29_DRC_1); CtrlReg |= 0x3; //mic volume 18 db snd_soc_write(codec, R29_DRC_1, CtrlReg); }else{ /* Mic Bias disable */ CtrlReg = (0x0<<0) | (0x0<<1); snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, CtrlReg); fm34_config_DSP(); } return 0; }
static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct adam_audio_priv* ctx = rtd->socdev->codec_data; int dai_flag = 0, sys_clk; int err; int i; /* Get the requested sampling rate */ unsigned int srate = params_rate(params); /* I2S <-> DAC <-> DAS <-> DAP <-> CODEC -If DAP is master, codec will be slave */ int codec_is_master = !tegra_das_is_port_master(tegra_audio_codec_type_hifi); /* Get DAS dataformat - DAP is connecting to codec */ enum dac_dap_data_format data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_hifi); /* We are supporting DSP and I2s format for now */ if (data_fmt & dac_dap_data_format_i2s) dai_flag |= SND_SOC_DAIFMT_I2S; else dai_flag |= SND_SOC_DAIFMT_DSP_A; if (codec_is_master) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; /* codec is master */ else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; pr_debug("%s(): format: 0x%08x\n", __FUNCTION__,params_format(params)); /* Set the CPU dai format. This will also set the clock rate in master mode */ err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { pr_err("cpu_dai fmt not set \n"); return err; } err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { pr_err("codec_dai fmt not set \n"); return err; } /* Get system clock */ sys_clk = clk_get_rate(ctx->dap_mclk); /* Set CPU sysclock as the same - in Tegra, seems to be a NOP */ err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } if (codec_is_master) { pr_debug("%s(): codec in master mode\n",__FUNCTION__); /* If using port as slave (=codec as master), then we can use the codec PLL to get the other sampling rates */ /* Try each one until success */ for (i = 0; i < ARRAY_SIZE(clocktab); i++) { if (clocktab[i].srate != srate) continue; if (snd_soc_dai_set_pll(codec_dai, 0, 0, sys_clk, clocktab[i].mclk) >= 0) { /* Codec PLL is synthetizing this new clock */ sys_clk = clocktab[i].mclk; break; } } if (i >= ARRAY_SIZE(clocktab)) { pr_err("%s(): unable to set required MCLK for SYSCLK of %d, sampling rate: %d\n",__FUNCTION__,sys_clk,srate); return -EINVAL; } } else { pr_debug("%s(): codec in slave mode\n",__FUNCTION__); /* Disable codec PLL */ err = snd_soc_dai_set_pll(codec_dai, 0, 0, sys_clk, sys_clk); if (err < 0) { pr_err("%s(): unable to disable codec PLL\n",__FUNCTION__); return err; } /* Check this sampling rate can be achieved with this sysclk */ for (i = 0; i < ARRAY_SIZE(clocktab); i++) { if (clocktab[i].srate != srate) continue; if (sys_clk == clocktab[i].mclk) break; } if (i >= ARRAY_SIZE(clocktab)) { pr_err("%s(): unable to get required %d hz sampling rate of %d hz SYSCLK\n",__FUNCTION__,srate,sys_clk); return -EINVAL; } } /* Set CODEC sysclk */ err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("codec_dai clock not set\n"); return err; } return 0; }
static int tegra_voice_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct adam_audio_priv* ctx = rtd->socdev->codec_data; int dai_flag = 0, sys_clk; int err; /* Get DAS dataformat and master flag */ int codec_is_master = !tegra_das_is_port_master(tegra_audio_codec_type_bluetooth); enum dac_dap_data_format data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_bluetooth); /* We are supporting DSP and I2s format for now */ if (data_fmt & dac_dap_data_format_dsp) dai_flag |= SND_SOC_DAIFMT_DSP_A; else dai_flag |= SND_SOC_DAIFMT_I2S; if (codec_is_master) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; /* codec is master */ else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; pr_debug("%s(): format: 0x%08x\n", __FUNCTION__,params_format(params)); /* Set the CPU dai format. This will also set the clock rate in master mode */ err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { pr_err("cpu_dai fmt not set \n"); return err; } /* Bluetooth Codec is always slave here */ err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { pr_err("codec_dai fmt not set \n"); return err; } /* Get system clock */ sys_clk = clk_get_rate(ctx->dap_mclk); /* Set CPU sysclock as the same - in Tegra, seems to be a NOP */ err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } /* Set CODEC sysclk */ err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } return 0; }
static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_codec *codec = codec_dai->codec; struct tegra_audio_data* audio_data = rtd->socdev->codec_data; enum dac_dap_data_format data_fmt; int dai_flag = 0, sys_clk; int err; //printk(KERN_INFO "####### tegra_hifi_hw_params type:%d\n", substream->stream); if (tegra_das_is_port_master(tegra_audio_codec_type_hifi)) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_hifi); /* We are supporting DSP and I2s format for now */ if (data_fmt & dac_dap_data_format_i2s) dai_flag |= SND_SOC_DAIFMT_I2S; else dai_flag |= SND_SOC_DAIFMT_DSP_A; err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { pr_err("codec_dai fmt not set \n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { pr_err("cpu_dai fmt not set \n"); return err; } sys_clk = clk_get_rate(audio_data->dap_mclk); err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("codec_dai clock not set\n"); return err; } err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) { int CtrlReg = 0; int VolumeCtrlReg = 0; //int SidetoneCtrlReg = 0; #if 0 snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, 0X7); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, 0X7); /* Mic Bias enable */ CtrlReg = (0x1<<B00_MICBIAS_ENA) | (0x1<<B01_MICDET_ENA); snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, CtrlReg); /* Enable DRC */ CtrlReg = snd_soc_read(codec, WM8903_DRC_0); CtrlReg |= (1<<B15_DRC_ENA); snd_soc_write(codec, WM8903_DRC_0, CtrlReg); #endif /* Single Ended Mic */ CtrlReg = (0x1<<B06_IN_CM_ENA) | (0x0<<B00_MODE) | (0x1<<B04_IP_SEL_N) | (0x1<<B02_IP_SEL_P); VolumeCtrlReg = (0x1B << B00_IN_VOL); /* Mic Setting */ snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_1, CtrlReg); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_1, CtrlReg); /* voulme for single ended mic */ snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, VolumeCtrlReg); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, VolumeCtrlReg); /* replicate mic setting on both channels */ CtrlReg = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_0); CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCR, 0x0); CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCL, 0x0); snd_soc_write(codec, WM8903_AUDIO_INTERFACE_0, CtrlReg); /* Enable analog inputs */ CtrlReg = (0x1<<B01_INL_ENA) | (0x1<<B00_INR_ENA); snd_soc_write(codec, WM8903_POWER_MANAGEMENT_0, CtrlReg); /* ADC Settings */ //CtrlReg = snd_soc_read(codec, WM8903_ADC_DIGITAL_0); CtrlReg = (0x01<<WM8903_ADC_HPF_CUT_SHIFT) | WM8903_ADC_HPF_ENA; snd_soc_write(codec, WM8903_ADC_DIGITAL_0, CtrlReg); //SidetoneCtrlReg = 0; //snd_soc_write(codec, R20_SIDETONE_CTRL, SidetoneCtrlReg); /* Enable ADC */ CtrlReg = snd_soc_read(codec, WM8903_POWER_MANAGEMENT_6); CtrlReg |= (0x1<<B01_ADCL_ENA); snd_soc_write(codec, WM8903_POWER_MANAGEMENT_6, CtrlReg); #if 0 CtrlReg = snd_soc_read(codec, R29_DRC_1); CtrlReg |= 0x3; /*mic volume 18 db */ snd_soc_write(codec, R29_DRC_1, CtrlReg); #endif mic_mute_state = 0; } return 0; }
static int tegra_hifi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_codec *codec = codec_dai->codec; struct tegra_audio_data* audio_data = rtd->socdev->codec_data; enum dac_dap_data_format data_fmt; int dai_flag = 0, sys_clk; int err; if (tegra_das_is_port_master(tegra_audio_codec_type_hifi)) dai_flag |= SND_SOC_DAIFMT_CBM_CFM; else dai_flag |= SND_SOC_DAIFMT_CBS_CFS; data_fmt = tegra_das_get_codec_data_fmt(tegra_audio_codec_type_hifi); /* We are supporting DSP and I2s format for now */ if (data_fmt & dac_dap_data_format_i2s) dai_flag |= SND_SOC_DAIFMT_I2S; else dai_flag |= SND_SOC_DAIFMT_DSP_A; err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { pr_err("codec_dai fmt not set \n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { pr_err("cpu_dai fmt not set \n"); return err; } sys_clk = clk_get_rate(audio_data->dap_mclk); err = snd_soc_dai_set_sysclk(codec_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("codec_dai clock not set\n"); return err; } err = snd_soc_dai_set_sysclk(cpu_dai, 0, sys_clk, SND_SOC_CLOCK_IN); if (err < 0) { pr_err("cpu_dai clock not set\n"); return err; } if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) { int CtrlReg = 0; int VolumeCtrlReg = 0; int SidetoneCtrlReg = 0; snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, 0X7); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, 0X7); /* Mic Bias enable */ CtrlReg = (0x1<<B00_MICBIAS_ENA) | (0x1<<B01_MICDET_ENA); snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, CtrlReg); /* Enable DRC */ CtrlReg = snd_soc_read(codec, WM8903_DRC_0); CtrlReg |= (1<<B15_DRC_ENA); snd_soc_write(codec, WM8903_DRC_0, CtrlReg); /* Single Ended Mic */ #if defined(CONFIG_MACH_ACER_PICASSO) || defined(CONFIG_MACH_ACER_MAYA) if (wired_jack_state() == 1) { CtrlReg = (0x0<<B06_IN_CM_ENA) | (0x0<<B00_MODE) | (0x1<<B04_IP_SEL_N) | (0x1<<B02_IP_SEL_P); } else { CtrlReg = (0x0<<B06_IN_CM_ENA) | (0x0<<B00_MODE) | (0x0<<B04_IP_SEL_N) | (0x1<<B02_IP_SEL_P); } #elif defined(CONFIG_MACH_ACER_VANGOGH) if (wired_jack_state() == 1) { select_mic_input(1); } else { select_mic_input(2); } CtrlReg = (0x0<<B06_IN_CM_ENA) | (0x0<<B00_MODE) | (0x0<<B04_IP_SEL_N) | (0x1<<B02_IP_SEL_P); #else CtrlReg = (0x0<<B06_IN_CM_ENA) | (0x0<<B00_MODE) | (0x0<<B04_IP_SEL_N) | (0x1<<B02_IP_SEL_P); #endif #if defined(CONFIG_MACH_ACER_PICASSO) || defined(CONFIG_MACH_ACER_MAYA) || defined(CONFIG_MACH_ACER_VANGOGH) VolumeCtrlReg = (0x10 << B00_IN_VOL); #else VolumeCtrlReg = (0x1C << B00_IN_VOL); #endif /* Mic Setting */ snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_1, CtrlReg); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_1, CtrlReg); /* voulme for single ended mic */ snd_soc_write(codec, WM8903_ANALOGUE_LEFT_INPUT_0, VolumeCtrlReg); snd_soc_write(codec, WM8903_ANALOGUE_RIGHT_INPUT_0, VolumeCtrlReg); /* Left ADC data on both channels */ CtrlReg = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_0); CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCR, 0x0); CtrlReg = SET_REG_VAL(CtrlReg, 0x1, B06_AIF_ADCL, 0x0); snd_soc_write(codec, WM8903_AUDIO_INTERFACE_0, CtrlReg); /* Enable analog inputs */ #if defined(CONFIG_MACH_ACER_PICASSO) || defined(CONFIG_MACH_ACER_MAYA) || defined(CONFIG_MACH_ACER_VANGOGH) if (audio_data->isMicMuted) CtrlReg = (0x0<<B01_INL_ENA); else CtrlReg = (0x1<<B01_INL_ENA); #else CtrlReg = (0x1<<B01_INL_ENA); #endif snd_soc_write(codec, WM8903_POWER_MANAGEMENT_0, CtrlReg); /* ADC Settings */ CtrlReg = snd_soc_read(codec, WM8903_ADC_DIGITAL_0); CtrlReg |= (0x1<<B04_ADC_HPF_ENA); snd_soc_write(codec, WM8903_ADC_DIGITAL_0, CtrlReg); /* Disable sidetone */ CtrlReg = 0; snd_soc_write(codec, R20_SIDETONE_CTRL, CtrlReg); /* Enable ADC */ CtrlReg = snd_soc_read(codec, WM8903_POWER_MANAGEMENT_6); CtrlReg |= (0x1<<B01_ADCL_ENA); snd_soc_write(codec, WM8903_POWER_MANAGEMENT_6, CtrlReg); CtrlReg = snd_soc_read(codec, R29_DRC_1); CtrlReg |= 0x3; /*mic volume 18 db */ snd_soc_write(codec, R29_DRC_1, CtrlReg); configure_dmic(codec); } #if defined(CONFIG_MACH_ACER_PICASSO) || defined(CONFIG_MACH_ACER_MAYA) snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, 0xB7); snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, 0xB7); #elif defined(CONFIG_MACH_ACER_VANGOGH) snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, 0xB3); snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, 0xB3); #else snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, 0xB7); snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, 0xB7); #endif return 0; }