/* * Should only be called when port is inactive. * although can be called multiple times by upper layers. */ static int mxs_saif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); struct mxs_saif *master_saif; u32 scr, stat; int ret; master_saif = mxs_saif_get_master(saif); if (!master_saif) return -EINVAL; /* mclk should already be set */ if (!saif->mclk && saif->mclk_in_use) { dev_err(cpu_dai->dev, "set mclk first\n"); return -EINVAL; } stat = __raw_readl(saif->base + SAIF_STAT); if (stat & BM_SAIF_STAT_BUSY) { dev_err(cpu_dai->dev, "error: busy\n"); return -EBUSY; } /* * Set saif clk based on sample rate. * If mclk is used, we also set mclk, if not, saif->mclk is * default 0, means not used. */ ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params)); if (ret) { dev_err(cpu_dai->dev, "unable to get proper clk\n"); return ret; } /* prepare clk in hw_param, enable in trigger */ clk_prepare(saif->clk); if (saif != master_saif) { /* * Set an initial clock rate for the saif internal logic to work * properly. This is important when working in EXTMASTER mode * that uses the other saif's BITCLK&LRCLK but it still needs a * basic clock which should be fast enough for the internal * logic. */ clk_enable(saif->clk); ret = clk_set_rate(saif->clk, 24000000); clk_disable(saif->clk); if (ret) return ret; clk_prepare(master_saif->clk); } scr = __raw_readl(saif->base + SAIF_CTRL); scr &= ~BM_SAIF_CTRL_WORD_LENGTH; scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: scr |= BF_SAIF_CTRL_WORD_LENGTH(0); break; case SNDRV_PCM_FORMAT_S20_3LE: scr |= BF_SAIF_CTRL_WORD_LENGTH(4); scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; break; case SNDRV_PCM_FORMAT_S24_LE: scr |= BF_SAIF_CTRL_WORD_LENGTH(8); scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; break; default: return -EINVAL; } /* Tx/Rx config */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* enable TX mode */ scr &= ~BM_SAIF_CTRL_READ_MODE; } else { /* enable RX mode */ scr |= BM_SAIF_CTRL_READ_MODE; } __raw_writel(scr, saif->base + SAIF_CTRL); return 0; }
static int uda134x_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); unsigned int hw_params = 0; if (substream == uda134x->slave_substream) { pr_debug("%s ignoring hw_params for slave substream\n", __func__); return 0; } pr_debug("%s sysclk: %d, rate:%d\n", __func__, uda134x->sysclk, params_rate(params)); /* set SYSCLK / fs ratio */ switch (uda134x->sysclk / params_rate(params)) { case 512: break; case 384: hw_params |= (1<<4); break; case 256: hw_params |= (1<<5); break; default: printk(KERN_ERR "%s unsupported fs\n", __func__); return -EINVAL; } pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__, uda134x->dai_fmt, params_format(params)); /* set DAI format and word length */ switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: break; case SND_SOC_DAIFMT_RIGHT_J: switch (params_width(params)) { case 16: hw_params |= (1<<1); break; case 18: hw_params |= (1<<2); break; case 20: hw_params |= ((1<<2) | (1<<1)); break; default: printk(KERN_ERR "%s unsupported format (right)\n", __func__); return -EINVAL; } break; case SND_SOC_DAIFMT_LEFT_J: hw_params |= (1<<3); break; default: printk(KERN_ERR "%s unsupported format\n", __func__); return -EINVAL; } return regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, STATUS0_SYSCLK_MASK | STATUS0_DAIFMT_MASK, hw_params); }
static int rk29_aif2_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; unsigned int pll_out = 0; int div_bclk,div_mclk; int ret; struct clk *general_pll; //change to 8Khz // params->intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = 8000; DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); // if (params_rate(params) != 8000) // return -EINVAL; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) { printk("%s: snd_soc_dai_set_fmt err =%d\n",__FUNCTION__,ret); return ret; } switch(params_rate(params)) { case 8000: case 16000: case 24000: case 32000: case 48000: pll_out = 12288000; break; case 11025: case 22050: case 44100: pll_out = 11289600; break; default: DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); return -EINVAL; } general_pll=clk_get(NULL, "general_pll"); if(clk_get_rate(general_pll)>260000000) { div_bclk=(pll_out/4)/params_rate(params)-1; div_mclk=3; } else if(clk_get_rate(general_pll)>130000000) { div_bclk=(pll_out/2)/params_rate(params)-1; div_mclk=1; } else {//96M pll_out=pll_out/4; div_bclk=(pll_out)/params_rate(params)-1; div_mclk=0; } DBG("func is%s,gpll=%ld,pll_out=%d,div_mclk=%d\n", __FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); if(ret < 0) { DBG("rk29_hw_params_wm8994:failed to set the cpu sysclk for codec side\n"); return ret; } snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); /* set the codec FLL */ ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, WM8994_FLL_SRC_MCLK1, pll_out, 8000 * 256); if (ret < 0) { printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); return ret; } /* set the codec system clock */ ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2, 8000 * 256, SND_SOC_CLOCK_IN); if (ret < 0) { printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); return ret; } return ret; }
/* Note that PCM works __only__ in AP-Master mode */ static int smdk_socpcm_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; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; int rfs, ret; unsigned long epll_out_rate; switch (params_rate(params)) { case 8000: case 12000: case 16000: case 24000: case 32000: case 48000: case 64000: case 96000: epll_out_rate = 49152000; break; case 11025: case 22050: case 44100: case 88200: epll_out_rate = 67738000; break; default: printk(KERN_ERR "%s:%d Sampling Rate %u not supported!\n", __func__, __LINE__, params_rate(params)); return -EINVAL; } switch (params_rate(params)) { case 16000: case 22050: case 22025: case 32000: case 44100: case 48000: case 96000: case 24000: rfs = 256; break; case 64000: rfs = 384; break; case 8000: case 11025: case 12000: rfs = 512; break; case 88200: rfs = 128; break; default: printk(KERN_ERR "%s:%d Sampling Rate %u not supported!\n", __func__, __LINE__, params_rate(params)); return -EINVAL; } /* Set the Codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; /* Set the AP DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; /* Set MUX for PCM clock source to audio-bus */ ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_PCM_CLKSRC_MUX, 0, SND_SOC_CLOCK_OUT); if (ret < 0) return ret; /* Set EPLL clock rate */ ret = set_epll_rate(epll_out_rate); if (ret < 0) return ret; /* Set SCLK_DIV for making bclk */ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_PCM_SCLK_PER_FS, rfs); if (ret < 0) return ret; /* Set WM8580 to drive MCLK from PLLA */ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, WM8580_CLKSRC_PLLA); if (ret < 0) return ret; /* Explicitly set WM8580-DAC to source from MCLK */ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_DAC_CLKSEL, WM8580_CLKSRC_MCLK); if (ret < 0) return ret; /* Explicitly set WM8580-ADC to source from MCLK */ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_ADC_CLKSEL, WM8580_CLKSRC_ADCMCLK); if (ret < 0) return ret; ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, SMDK_WM8580_XTI_FREQ, params_rate(params) * rfs); if (ret < 0) return ret; return 0; }
static int sta529_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; int pdata, play_freq_val, record_freq_val; int bclk_to_fs_ratio; switch (params_width(params)) { case 16: pdata = 1; bclk_to_fs_ratio = 0; break; case 24: pdata = 2; bclk_to_fs_ratio = 1; break; case 32: pdata = 3; bclk_to_fs_ratio = 2; break; default: dev_err(codec->dev, "Unsupported format\n"); return -EINVAL; } switch (params_rate(params)) { case 8000: case 11025: play_freq_val = 0; record_freq_val = 2; break; case 16000: case 22050: play_freq_val = 1; record_freq_val = 0; break; case 32000: case 44100: case 48000: play_freq_val = 2; record_freq_val = 0; break; default: dev_err(codec->dev, "Unsupported rate\n"); return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { snd_soc_update_bits(codec, STA529_S2PCFG1, PDATA_LEN_MSK, pdata << 6); snd_soc_update_bits(codec, STA529_S2PCFG1, BCLK_TO_FS_MSK, bclk_to_fs_ratio << 4); snd_soc_update_bits(codec, STA529_MISC, PLAY_FREQ_RANGE_MSK, play_freq_val << 4); } else { snd_soc_update_bits(codec, STA529_P2SCFG1, PDATA_LEN_MSK, pdata << 6); snd_soc_update_bits(codec, STA529_P2SCFG1, BCLK_TO_FS_MSK, bclk_to_fs_ratio << 4); snd_soc_update_bits(codec, STA529_MISC, CAP_FREQ_RANGE_MSK, record_freq_val << 2); } return 0; }
static int zylonite_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; unsigned int pll_out = 0; unsigned int wm9713_div = 0; int ret = 0; int rate = params_rate(params); int width = snd_pcm_format_physical_width(params_format(params)); /* Only support ratios that we can generate neatly from the AC97 * based master clock - in particular, this excludes 44.1kHz. * In most applications the voice DAC will be used for telephony * data so multiples of 8kHz will be the common case. */ switch (rate) { case 8000: wm9713_div = 12; break; case 16000: wm9713_div = 6; break; case 48000: wm9713_div = 2; break; default: /* Don't support OSS emulation */ return -EINVAL; } /* Add 1 to the width for the leading clock cycle */ pll_out = rate * (width + 1) * 8; ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); if (ret < 0) return ret; ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, pll_out); if (ret < 0) return ret; if (clk_pout) ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, WM9713_PCMDIV(wm9713_div)); else ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, WM9713_PCMDIV(wm9713_div)); if (ret < 0) return ret; ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; return 0; }
static int msm_hdmi_audio_codec_rx_dai_hw_params( struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { u32 channel_allocation = 0; u32 level_shift = 0; /* 0dB */ bool down_mix = 0; u32 num_channels = params_channels(params); int rv = 0; struct msm_hdmi_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->codec->dev); rv = codec_data->hdmi_ops.hdmi_cable_status( codec_data->hdmi_core_pdev, 1); if (IS_ERR_VALUE(rv)) { dev_err(dai->dev, "%s() HDMI core is not ready\n", __func__); return rv; } switch (num_channels) { case 2: channel_allocation = 0; break; case 3: channel_allocation = 0x02;//default to FL/FR/FC break; case 4: channel_allocation = 0x06;//default to FL/FR/FC/RC break; case 5: channel_allocation = 0x0A;//default to FL/FR/FC/RR/RL break; case 6: channel_allocation = 0x0B; break; case 7: channel_allocation = 0x12;//default to FL/FR/FC/RL/RR/RRC/RLC break; case 8: channel_allocation = 0x13; break; default: dev_err(dai->dev, "invalid Channels = %u\n", num_channels); return -EINVAL; } dev_dbg(dai->dev, "%s() num_ch %u samplerate %u channel_allocation = %u\n", __func__, num_channels, params_rate(params), channel_allocation); rv = codec_data->hdmi_ops.audio_info_setup( codec_data->hdmi_core_pdev, params_rate(params), num_channels, channel_allocation, level_shift, down_mix); if (IS_ERR_VALUE(rv)) { dev_err(dai->dev, "%s() HDMI core is not ready\n", __func__); } return rv; }
static int archos_wm8985_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; int ret,i; /* Set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) { printk(KERN_ERR "can't set codec DAI fmt configuration\n"); return ret; } /* Set cpu DAI configuration */ if (archos_spdif_func) { /* SPDIF Enabled, we need to configure MCBSP as a SPDIF output */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_SPDIF | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBM_CFM); } else { /* SPDIF Disable, we need to configure MCBSP as a PCM output */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBM_CFM); } if (ret < 0) { printk(KERN_ERR "can't set cpu DAI configuration\n"); return ret; } /* Set PPL and divisor here and not in the codec, since it's our board which requires these settings */ //printk(KERN_INFO "archos_wm8985_hw_params : freq = %d, channels = %d\n", params_rate(params), params_channels(params)); for(i = 0; i < sample_count; i++) { if (params_rate(params) == sample_info[i].sample_rate) { //printk(KERN_INFO "archos_hw_params : selected id = %d\n", i); /* PPL (WM8985 is Master) */ ret = snd_soc_dai_set_pll(codec_dai, 0, mclk,sample_info[i].out_hz); if (ret < 0) { printk(KERN_ERR "can't set codec DAI ppl configuration\n"); return ret; } /* MCLK/BCLK stuff */ ret = snd_soc_dai_set_clkdiv(codec_dai,WM8985_MCLKSEL, WM8985_MCLK_PLL); if (ret < 0) { printk(KERN_ERR "can't set codec DAI MCLKSEL configuration\n"); return ret; } ret = snd_soc_dai_set_clkdiv(codec_dai,WM8985_MCLKDIV, sample_info[i].mclk_div << 5); if (ret < 0) { printk(KERN_ERR "can't set codec DAI MCLKDIV configuration\n"); return ret; } ret = snd_soc_dai_set_clkdiv(codec_dai,WM8985_BCLKDIV, sample_info[i].bclk_div << 2); if (ret < 0) { printk(KERN_ERR "can't set codec DAI BCLKDIV configuration\n"); return ret; } } } /* The codec may need to know the MCLK (Sample Rate for DAC and ADC are set by the codec) */ ret = snd_soc_dai_set_sysclk(codec_dai, WM8985_ID_MCLK, mclk, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "can't set codec system clock\n"); return ret; } return 0; }
static void set_st_params(struct oxygen *chip, struct snd_pcm_hw_params *params) { update_cs2000_rate(chip, params_rate(params)); set_pcm1796_params(chip, params); }
static int tegra_rt5631_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_rt5631 *machine = snd_soc_card_get_drvdata(card); int srate, mclk, i2s_daifmt; int err; srate = params_rate(params); switch (srate) { case 64000: case 88200: case 96000: mclk = 128 * srate; break; default: mclk = 384 * srate; break; } /* FIXME: Codec only requires >= 3MHz if OSR==0 */ while (mclk < 6000000) mclk *= 2; err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { dev_err(card->dev, "Can't configure clocks\n"); return err; } i2s_daifmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; /* Use DSP mode for mono on Tegra20 */ if ((params_channels(params) != 2) && (machine_is_ventana() || machine_is_harmony() || machine_is_kaen() || machine_is_aebl())) i2s_daifmt |= SND_SOC_DAIFMT_DSP_A; else i2s_daifmt |= SND_SOC_DAIFMT_I2S; err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "codec_dai fmt not set\n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "cpu_dai fmt not set\n"); return err; } err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; } return 0; }
static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { int err = 0; struct snd_aes_iec958 iec; struct snd_cea_861_aud_if cea; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: omap_hdmi_dai_dma_params.packet_size = 16; break; case SNDRV_PCM_FORMAT_S24_LE: omap_hdmi_dai_dma_params.packet_size = 32; break; default: err = -EINVAL; } omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; snd_soc_dai_set_dma_data(dai, substream, &omap_hdmi_dai_dma_params); /* Fill IEC 60958 channel status word */ /* TODO: no need to fill with zeros when using kzalloc */ iec.status[0] = 0; iec.status[1] = 0; iec.status[2] = 0; iec.status[3] = 0; iec.status[4] = 0; iec.status[5] = 0; /* Fill CEA 861 audio infoframe */ /* here fill commercial use (0) */ iec.status[0] &= ~IEC958_AES0_PROFESSIONAL; /* here fill lpcm audio (0) */ iec.status[0] &= ~IEC958_AES0_NONAUDIO; /* here fill copyright info */ iec.status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT; /* here fill emphasis info */ iec.status[0] |= IEC958_AES0_CON_EMPHASIS_NONE; /* here fill mode info */ iec.status[0] |= IEC958_AES1_PRO_MODE_NOTID; /* here fill category */ iec.status[1] = IEC958_AES1_CON_GENERAL; /* here fill the source number */ iec.status[2] |= IEC958_AES2_CON_SOURCE_UNSPEC; /* here fill the channel number */ iec.status[2] |= IEC958_AES2_CON_CHANNEL_UNSPEC; /* here fill sampling rate */ switch (params_rate(params)) { case 32000: iec.status[3] |= IEC958_AES3_CON_FS_32000; break; case 44100: iec.status[3] |= IEC958_AES3_CON_FS_44100; break; case 48000: iec.status[3] |= IEC958_AES3_CON_FS_48000; break; case 88200: iec.status[3] |= IEC958_AES3_CON_FS_88200; break; case 96000: iec.status[3] |= IEC958_AES3_CON_FS_96000; break; case 176400: iec.status[3] |= IEC958_AES3_CON_FS_176400; break; case 192000: iec.status[3] |= IEC958_AES3_CON_FS_192000; break; default: return -EINVAL; } /* here fill the clock accuracy */ iec.status[3] |= IEC958_AES3_CON_CLOCK_1000PPM; /* here fill the word length */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: iec.status[4] |= IEC958_AES4_CON_WORDLEN_20_16; iec.status[4] |= 0; /* replace with word max define */ break; case SNDRV_PCM_FORMAT_S24_LE: iec.status[4] |= IEC958_AES4_CON_WORDLEN_24_20; iec.status[4] |= IEC958_AES4_CON_MAX_WORDLEN_24; break; default: err = -EINVAL; } /* Fill the CEA 861 audio infoframe. Refer to the specification * for details. * The OMAP HDMI IP requires to use the 8-channel channel code when * transmitting more than two channels. */ if (params_channels(params) == 2) cea.db4_ca = 0x0; else cea.db4_ca = 0x13; cea.db1_ct_cc = (params_channels(params) - 1) & CEA861_AUDIO_INFOFRAME_DB1CC; cea.db1_ct_cc |= CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM; cea.db2_sf_ss = CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM; cea.db2_sf_ss |= CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM; cea.db3 = 0; /* not used, all zeros */ cea.db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED; cea.db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV); hdmi.iec = iec; hdmi.cea = cea; err = hdmi.dssdev->driver->audio_config(hdmi.dssdev, &hdmi.iec, &hdmi.cea); return err; }
static int rk29_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; #else struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; #endif int ret; unsigned int pll_out = 0; int div_bclk,div_mclk; // struct clk *general_pll; DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); /*by Vincent Hsiung for EQ Vol Change*/ #define HW_PARAMS_FLAG_EQVOL_ON 0x21 #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent #else ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent #endif DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); } else { /* set codec DAI configuration */ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) ret = codec_dai->driver->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); #else ret = codec_dai->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); #endif #endif #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) ret = codec_dai->driver->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); #else ret = codec_dai->ops->set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); #endif #endif if (ret < 0) return ret; /* set cpu DAI configuration */ DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) ret = cpu_dai->driver->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); #else ret = cpu_dai->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); #endif #endif #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) ret = cpu_dai->driver->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); #else ret = cpu_dai->ops->set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); #endif #endif if (ret < 0) return ret; } switch(params_rate(params)) { case 8000: case 16000: case 24000: case 32000: case 48000: case 96000: pll_out = 12288000; break; case 11025: case 22050: case 44100: case 88200: pll_out = 11289600; break; case 176400: pll_out = 11289600*2; break; case 192000: pll_out = 12288000*2; break; default: DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); return -EINVAL; break; } DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); #endif #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) div_bclk = 63; div_mclk = pll_out/(params_rate(params)*64) - 1; // DBG("func is%s,gpll=%ld,pll_out=%ld,div_mclk=%ld\n", // __FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); // DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); #endif 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_aic3008 *machine = snd_soc_card_get_drvdata(card); int dai_flag = 0, mclk, srate; int err; AUD_DBG("Start tegra_hifi_hw_params()\n"); AUD_DBG("set I2S Master\n"); dai_flag |= SND_SOC_DAIFMT_I2S; // i2s mode dai_flag |= SND_SOC_DAIFMT_CBM_CFM; // bclk and frame master srate = params_rate(params); switch (srate) { case 64000: case 88200: case 96000: mclk = 128 * srate; break; default: mclk = 256 * srate; break; } /* FIXME: Codec only requires >= 3MHz if OSR==0 */ while (mclk < 6000000) mclk *= 2; mclk = 12288000; err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { dev_err(card->dev, "Can't configure clocks\n"); return err; } // eventually calls audio codec to set dai format, which sets slave err = snd_soc_dai_set_fmt(codec_dai, dai_flag); if (err < 0) { AUD_ERR("codec_dai fmt not set \n"); return err; } AUD_DBG("*** snd_soc_dai_set_fmt(codec_dai, dai_flag) ok ***\n"); // eventually calls t2s driver to set dai format, which sets master err = snd_soc_dai_set_fmt(cpu_dai, dai_flag); if (err < 0) { AUD_ERR("cpu_dai fmt not set \n"); return err; } AUD_DBG("*** snd_soc_dai_set_fmt(cpu_dai, dai_flag) ok ***\n"); // FIXME: not sure this is the right way. // Sets the audio codec clks. // This should be sample rate times 256 or 128 based on codec need err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { AUD_ERR("codec_dai clock not set\n"); return err; } AUD_DBG("*** snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN) ok ***\n"); 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; }
/** * cs42888_hw_params - program the CS42888 with the given hardware parameters. * @substream: the audio stream * @params: the hardware parameters to set * @dai: the SOC DAI (ignored) * * This function programs the hardware with the values provided. * Specifically, the sample rate and the data format. * * The .ops functions are used to provide board-specific data, like input * frequencies, to this driver. This function takes that information, * combines it with the hardware parameters provided, and programs the * hardware accordingly. */ static int cs42888_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct cs42888_private *cs42888 = codec->private_data; int ret; unsigned int i; unsigned int rate; unsigned int ratio; u8 val; rate = params_rate(params); /* Sampling rate, in Hz */ ratio = cs42888->mclk / rate; /* MCLK/LRCK ratio */ for (i = 0; i < NUM_MCLK_RATIOS; i++) { if (cs42888_mode_ratios[i].ratio == ratio) break; } if (i == NUM_MCLK_RATIOS) { /* We did not find a matching ratio */ dev_err(codec->dev, "could not find matching ratio\n"); return -EINVAL; } if (!cs42888->slave_mode) { val = cs42888_read_reg_cache(codec, CS42888_MODE); val &= ~CS42888_MODE_SPEED_MASK; val |= cs42888_mode_ratios[i].speed_mode; val &= ~CS42888_MODE_DIV_MASK; val |= cs42888_mode_ratios[i].mclk; } else { val = cs42888_read_reg_cache(codec, CS42888_MODE); val &= ~CS42888_MODE_SPEED_MASK; val |= CS42888_MODE_SLAVE; } ret = cs42888_i2c_write(codec, CS42888_MODE, val); if (ret < 0) { pr_err("i2c write failed\n"); return ret; } /* Out of low power state */ val = cs42888_read_reg_cache(codec, CS42888_PWRCTL); val &= ~CS42888_PWRCTL_PDN_MASK; ret = cs42888_i2c_write(codec, CS42888_PWRCTL, val); if (ret < 0) { pr_err("i2c write failed\n"); return ret; } /* Unmute all the channels */ val = cs42888_read_reg_cache(codec, CS42888_MUTE); val &= ~CS42888_MUTE_ALL; ret = cs42888_i2c_write(codec, CS42888_MUTE, val); if (ret < 0) { pr_err("i2c write failed\n"); return ret; } ret = cs42888_fill_cache(codec); if (ret < 0) { pr_err("failed to fill register cache\n"); return ret; } return ret; }
static int smdk6400_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_codec_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; unsigned int pll_out = 0, bclk = 0; int ret = 0; unsigned int regs; unsigned int prescaler=0; //s3cdbg("Entered %s, rate = %d\n", __FUNCTION__, params_rate(params)); printk("Entered %s, rate = %d\n", __FUNCTION__, params_rate(params)); /* Select Clock source EPLL */ // regs = ioremap(S3C2410_PA_CLKPWR,0x20); regs = readl(S3C2443_CLKSRC); regs &= ~(3<<12); regs &= ~(3<<14); regs |= S3C2450_CLKSRC_I2S1_EPLL; regs = (regs & ~(3<<7))|(2<<7); writel(regs, S3C2443_CLKSRC); regs |= (1<<6); writel(regs, S3C2443_CLKSRC); regs = readl(S3C2443_SCLKCON); regs |= S3C2443_SCLKCON_I2SCLK_1; writel(regs, S3C2443_SCLKCON); //s3cdbg("%s: %d , params = %d \n", __FUNCTION__, __LINE__, params_rate(params)); printk("%s: %d , params = %d \n", __FUNCTION__, __LINE__, params_rate(params)); switch (params_rate(params)) { case 8000: case 16000: case 32000: case 48000: case 64000: case 96000: writel(9962, S3C2450_EPLLCON_K); writel((49<<16)|(1<<8)|(3<<0) ,S3C2443_EPLLCON); break; case 11025: case 22050: case 44100: case 88200: writel(10381, S3C2450_EPLLCON_K); writel((45<<16)|(1<<8)|(2<<0) ,S3C2443_EPLLCON); break; default: printk("Unsupported rate = %d\n", params_rate(params)); break; } switch (params_rate(params)) { case 8000: bclk = WM8753_BCLK_DIV_16; pll_out = 18432000; prescaler = 24; break; case 11025: bclk = WM8753_BCLK_DIV_16; pll_out = 16934400; prescaler = 32; break; case 16000: bclk = WM8753_BCLK_DIV_8; pll_out = 18432000; prescaler = 12; break; case 22050: bclk = WM8753_BCLK_DIV_2; pll_out = 16934400; prescaler = 16; break; case 32000: bclk = WM8753_BCLK_DIV_4; pll_out = 18432000; prescaler = 6; break; case 44100: bclk = WM8753_BCLK_DIV_4; pll_out = 16934400; prescaler = 8; break; case 48000: bclk = WM8753_BCLK_DIV_4; pll_out = 18432000; prescaler = 4; break; case 64000: bclk = WM8753_BCLK_DIV_4; pll_out = 18432000; prescaler = 3; break; case 88200: bclk = WM8753_BCLK_DIV_4; pll_out = 16934400; prescaler = 4; break; case 96000: bclk = WM8753_BCLK_DIV_4; pll_out = 18432000; prescaler = 2; break; } /* set codec DAI configuration */ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS ); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS ); if (ret < 0) return ret; /* set the codec system clock for DAC and ADC */ ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_MCLK, pll_out, SND_SOC_CLOCK_IN); if (ret < 0) return ret; /* set MCLK division for sample rate */ ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, S3C2410_IISMOD_32FS ); if (ret < 0) return ret; /* set codec BCLK division for sample rate */ ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk); if (ret < 0) return ret; /* set prescaler division for sample rate */ ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, ((prescaler/2 - 1) << 0x8)); if (ret < 0) return ret; #if 0 /* set the codec register set for capture and play */ ret = codec_dai->dai_ops.set_tdm_slot(codec_dai, substream->stream, 2); if (ret < 0) return ret; #endif return 0; }
static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); unsigned int sampling_rate = params_rate(params); unsigned int data_length, data_delay, bclk_ratio; unsigned int ch1pos, ch2pos, mode, format; uint32_t csreg; /* * If a stream is already enabled, * the registers are already set properly. */ regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); if (csreg & (BCM2835_I2S_TXON | BCM2835_I2S_RXON)) return 0; /* * Adjust the data length according to the format. * We prefill the half frame length with an integer * divider of 2400 as explained at the clock settings. * Maybe it is overwritten there, if the Integer mode * does not apply. */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: data_length = 16; break; case SNDRV_PCM_FORMAT_S24_LE: data_length = 24; break; case SNDRV_PCM_FORMAT_S32_LE: data_length = 32; break; default: return -EINVAL; } /* If bclk_ratio already set, use that one. */ if (dev->bclk_ratio) bclk_ratio = dev->bclk_ratio; else /* otherwise calculate a fitting block ratio */ bclk_ratio = 2 * data_length; /* Clock should only be set up here if CPU is clock master */ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: case SND_SOC_DAIFMT_CBS_CFM: clk_set_rate(dev->clk, sampling_rate * bclk_ratio); break; default: break; } /* Setup the frame format */ format = BCM2835_I2S_CHEN; if (data_length >= 24) format |= BCM2835_I2S_CHWEX; format |= BCM2835_I2S_CHWID((data_length-8)&0xf); switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: data_delay = 1; break; default: /* * TODO * Others are possible but are not implemented at the moment. */ dev_err(dev->dev, "%s:bad format\n", __func__); return -EINVAL; } ch1pos = data_delay; ch2pos = bclk_ratio / 2 + data_delay; switch (params_channels(params)) { case 2: format = BCM2835_I2S_CH1(format) | BCM2835_I2S_CH2(format); format |= BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(ch1pos)); format |= BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(ch2pos)); break; default: return -EINVAL; } /* * Set format for both streams. * We cannot set another frame length * (and therefore word length) anyway, * so the format will be the same. */ regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format); regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format); /* Setup the I2S mode */ mode = 0; if (data_length <= 16) { /* * Use frame packed mode (2 channels per 32 bit word) * We cannot set another frame length in the second stream * (and therefore word length) anyway, * so the format will be the same. */ mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP; } mode |= BCM2835_I2S_FLEN(bclk_ratio - 1); mode |= BCM2835_I2S_FSLEN(bclk_ratio / 2); /* Master or slave? */ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* CPU is master */ break; case SND_SOC_DAIFMT_CBM_CFS: /* * CODEC is bit clock master * CPU is frame master */ mode |= BCM2835_I2S_CLKM; break; case SND_SOC_DAIFMT_CBS_CFM: /* * CODEC is frame master * CPU is bit clock master */ mode |= BCM2835_I2S_FSM; break; case SND_SOC_DAIFMT_CBM_CFM: /* CODEC is master */ mode |= BCM2835_I2S_CLKM; mode |= BCM2835_I2S_FSM; break; default: dev_err(dev->dev, "%s:bad master\n", __func__); return -EINVAL; } /* * Invert clocks? * * The BCM approach seems to be inverted to the classical I2S approach. */ switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: /* None. Therefore, both for BCM */ mode |= BCM2835_I2S_CLKI; mode |= BCM2835_I2S_FSI; break; case SND_SOC_DAIFMT_IB_IF: /* Both. Therefore, none for BCM */ break; case SND_SOC_DAIFMT_NB_IF: /* * Invert only frame sync. Therefore, * invert only bit clock for BCM */ mode |= BCM2835_I2S_CLKI; break; case SND_SOC_DAIFMT_IB_NF: /* * Invert only bit clock. Therefore, * invert only frame sync for BCM */ mode |= BCM2835_I2S_FSI; break; default: return -EINVAL; } regmap_write(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, mode); /* Setup the DMA parameters */ regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, BCM2835_I2S_RXTHR(1) | BCM2835_I2S_TXTHR(1) | BCM2835_I2S_DMAEN, 0xffffffff); regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_DREQ_A_REG, BCM2835_I2S_TX_PANIC(0x10) | BCM2835_I2S_RX_PANIC(0x30) | BCM2835_I2S_TX(0x30) | BCM2835_I2S_RX(0x20), 0xffffffff); /* Clear FIFOs */ bcm2835_i2s_clear_fifos(dev, true, true); return 0; }
static int arizona_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; int base = dai->driver->base; const int *rates; int i; int bclk, lrclk, wl, frame, sr_val; if (params_rate(params) % 8000) rates = &arizona_44k1_bclk_rates[0]; else rates = &arizona_48k_bclk_rates[0]; for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) { if (rates[i] >= snd_soc_params_to_bclk(params) && rates[i] % params_rate(params) == 0) { bclk = i; break; } } if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++) if (arizona_sr_vals[i] == params_rate(params)) break; if (i == ARRAY_SIZE(arizona_sr_vals)) { arizona_aif_err(dai, "Unsupported sample rate %dHz\n", params_rate(params)); return -EINVAL; } sr_val = i; lrclk = snd_soc_params_to_bclk(params) / params_rate(params); arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", rates[bclk], rates[bclk] / lrclk); wl = snd_pcm_format_width(params_format(params)); frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl; /* * We will need to be more flexible than this in future, * currently we use a single sample rate for SYSCLK. */ switch (dai_priv->clk) { case ARIZONA_CLK_SYSCLK: snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1, ARIZONA_SAMPLE_RATE_1_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 0); break; case ARIZONA_CLK_ASYNCCLK: snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, ARIZONA_AIF1_RATE_MASK, 8); break; default: arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); return -EINVAL; } snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL, ARIZONA_AIF1_BCLK_FREQ_MASK, bclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE, ARIZONA_AIF1TX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE, ARIZONA_AIF1RX_BCPF_MASK, lrclk); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1, ARIZONA_AIF1TX_WL_MASK | ARIZONA_AIF1TX_SLOT_LEN_MASK, frame); snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2, ARIZONA_AIF1RX_WL_MASK | ARIZONA_AIF1RX_SLOT_LEN_MASK, frame); return 0; }
static int wm8770_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec; struct wm8770_priv *wm8770; int i; int iface; int shift; int ratio; codec = dai->codec; wm8770 = snd_soc_codec_get_drvdata(codec); iface = 0; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; case SNDRV_PCM_FORMAT_S20_3LE: iface |= 0x10; break; case SNDRV_PCM_FORMAT_S24_LE: iface |= 0x20; break; case SNDRV_PCM_FORMAT_S32_LE: iface |= 0x30; break; } switch (substream->stream) { case SNDRV_PCM_STREAM_PLAYBACK: i = 0; shift = 4; break; case SNDRV_PCM_STREAM_CAPTURE: i = 2; shift = 0; break; default: return -EINVAL; } /* Only need to set MCLK/LRCLK ratio if we're master */ if (snd_soc_read(codec, WM8770_MSTRCTRL) & 0x100) { for (; i < ARRAY_SIZE(mclk_ratios); ++i) { ratio = wm8770->sysclk / params_rate(params); if (ratio == mclk_ratios[i]) break; } if (i == ARRAY_SIZE(mclk_ratios)) { dev_err(codec->dev, "Unable to configure MCLK ratio %d/%d\n", wm8770->sysclk, params_rate(params)); return -EINVAL; } dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]); snd_soc_update_bits(codec, WM8770_MSTRCTRL, 0x7 << shift, i << shift); } snd_soc_update_bits(codec, WM8770_IFACECTRL, 0x30, iface); return 0; }
static int smdk_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->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; unsigned int pll_out; int bfs, rfs, ret; switch (params_format(params)) { case SNDRV_PCM_FORMAT_U8: case SNDRV_PCM_FORMAT_S8: bfs = 16; break; case SNDRV_PCM_FORMAT_U16_LE: case SNDRV_PCM_FORMAT_S16_LE: bfs = 32; break; default: return -EINVAL; } /* The Fvco for WM8580 PLLs must fall within [90,100]MHz. * This criterion can't be met if we request PLL output * as {8000x256, 64000x256, 11025x256}Hz. * As a wayout, we rather change rfs to a minimum value that * results in (params_rate(params) * rfs), and itself, acceptable * to both - the CODEC and the CPU. */ switch (params_rate(params)) { case 16000: case 22050: case 32000: case 44100: case 48000: case 88200: case 96000: rfs = 256; break; case 64000: rfs = 384; break; case 8000: case 11025: rfs = 512; break; default: return -EINVAL; } pll_out = params_rate(params) * rfs; /* Set the Codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; /* Set the AP DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; /* Set WM8580 to drive MCLK from its PLLA */ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, WM8580_CLKSRC_PLLA); if (ret < 0) return ret; ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, SMDK_WM8580_FREQ, pll_out); if (ret < 0) return ret; ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA, pll_out, SND_SOC_CLOCK_IN); if (ret < 0) return ret; return 0; }
static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params, struct snd_soc_dai *dai, int stream) { struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev); u8 pgd_la, inf_la; u16 *slave_port_mapping; memset(dai_data->port_config.slimbus.slave_port_mapping, 0, sizeof(dai_data->port_config.slimbus.slave_port_mapping)); dai_data->channels = params_channels(params); slave_port_mapping = dai_data->port_config.slimbus.slave_port_mapping; switch (dai_data->channels) { case 4: if (dai->id == SLIMBUS_0_TX) { slave_port_mapping[0] = 7; slave_port_mapping[1] = 8; slave_port_mapping[2] = 9; slave_port_mapping[3] = 10; } else { return -EINVAL; } break; case 3: if (dai->id == SLIMBUS_0_TX) { slave_port_mapping[0] = 7; slave_port_mapping[1] = 8; slave_port_mapping[2] = 9; } else { return -EINVAL; } break; case 2: if (dai->id == SLIMBUS_0_RX) { slave_port_mapping[0] = 1; slave_port_mapping[1] = 2; } else { slave_port_mapping[0] = 7; slave_port_mapping[1] = 8; } break; case 1: if (dai->id == SLIMBUS_0_RX) slave_port_mapping[0] = 1; else slave_port_mapping[0] = 7; break; default: return -EINVAL; break; } dai_data->rate = params_rate(params); tabla_get_logical_addresses(&pgd_la, &inf_la); dai_data->port_config.slimbus.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1; dai_data->port_config.slimbus.slave_dev_pgd_la = pgd_la; dai_data->port_config.slimbus.slave_dev_intfdev_la = inf_la; /* Q6 only supports 16 as now */ dai_data->port_config.slimbus.bit_width = 16; dai_data->port_config.slimbus.data_format = 0; dai_data->port_config.slimbus.num_channels = dai_data->channels; dai_data->port_config.slimbus.reserved = 0; dev_dbg(dai->dev, "slimbus_dev_id %hu slave_dev_pgd_la 0x%hx\n" "slave_dev_intfdev_la 0x%hx bit_width %hu data_format %hu\n" "num_channel %hu slave_port_mapping[0] %hu\n" "slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n" "sample_rate %d\n", dai_data->port_config.slimbus.slimbus_dev_id, dai_data->port_config.slimbus.slave_dev_pgd_la, dai_data->port_config.slimbus.slave_dev_intfdev_la, dai_data->port_config.slimbus.bit_width, dai_data->port_config.slimbus.data_format, dai_data->port_config.slimbus.num_channels, dai_data->port_config.slimbus.slave_port_mapping[0], dai_data->port_config.slimbus.slave_port_mapping[1], dai_data->port_config.slimbus.slave_port_mapping[2], dai_data->rate); return 0; }
static int es705_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; /* struct es705_priv *es705 = snd_soc_codec_get_drvdata(codec); */ int bits_per_sample = 0; int rc = 0; dev_dbg(codec->dev, "%s(): dai->name = %s, dai->id = %d\n", __func__, dai->name, dai->id); switch (dai->id) { case 0: dev_dbg(codec->dev, "%s(): ES705_PORTA_PARAM_ID\n", __func__); break; case 1: dev_dbg(codec->dev, "%s(): ES705_PORTB_PARAM_ID\n", __func__); break; default: dev_dbg(codec->dev, "%s(): unknown port\n", __func__); return -EINVAL; } dev_dbg(codec->dev, "%s(): params_channels(params) = %d\n", __func__, params_channels(params)); switch (params_channels(params)) { case 1: dev_dbg(codec->dev, "%s(): 1 channel\n", __func__); break; case 2: dev_dbg(codec->dev, "%s(): 2 channels\n", __func__); break; case 4: dev_dbg(codec->dev, "%s(): 4 channels\n", __func__); break; default: dev_dbg(codec->dev, "%s(): unsupported number of channels\n", __func__); return -EINVAL; } dev_dbg(codec->dev, "%s(): params_rate(params) = %d\n", __func__, params_rate(params)); switch (params_rate(params)) { case 8000: dev_dbg(codec->dev, "%s(): 8000Hz\n", __func__); break; case 11025: dev_dbg(codec->dev, "%s(): 11025\n", __func__); break; case 16000: dev_dbg(codec->dev, "%s(): 16000\n", __func__); break; case 22050: dev_dbg(codec->dev, "%s(): 22050\n", __func__); break; case 32000: dev_dbg(codec->dev, "%s(): 32000\n", __func__); break; case 48000: dev_dbg(codec->dev, "%s(): 48000\n", __func__); break; case 96000: dev_dbg(codec->dev, "%s(): 96000\n", __func__); break; case 192000: dev_dbg(codec->dev, "%s(): 96000\n", __func__); break; default: dev_dbg(codec->dev, "%s(): unsupported rate = %d\n", __func__, params_rate(params)); return -EINVAL; } switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: dev_dbg(codec->dev, "%s(): S16_LE\n", __func__); bits_per_sample = 16; break; case SNDRV_PCM_FORMAT_S16_BE: dev_dbg(codec->dev, "%s(): S16_BE\n", __func__); bits_per_sample = 16; break; case SNDRV_PCM_FORMAT_S20_3LE: dev_dbg(codec->dev, "%s(): S20_3LE\n", __func__); bits_per_sample = 20; break; case SNDRV_PCM_FORMAT_S20_3BE: dev_dbg(codec->dev, "%s(): S20_3BE\n", __func__); bits_per_sample = 20; break; case SNDRV_PCM_FORMAT_S24_LE: dev_dbg(codec->dev, "%s(): S24_LE\n", __func__); bits_per_sample = 24; break; case SNDRV_PCM_FORMAT_S24_BE: dev_dbg(codec->dev, "%s(): S24_BE\n", __func__); bits_per_sample = 24; break; case SNDRV_PCM_FORMAT_S32_LE: dev_dbg(codec->dev, "%s(): S32_LE\n", __func__); bits_per_sample = 32; break; case SNDRV_PCM_FORMAT_S32_BE: dev_dbg(codec->dev, "%s(): S32_BE\n", __func__); bits_per_sample = 32; break; default: dev_dbg(codec->dev, "%s(): unknown format\n", __func__); return -EINVAL; } if (rc) { dev_dbg(codec->dev, "%s(): snd_soc_update_bits() failed\n", __func__); return rc; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dev_dbg(codec->dev, "%s(): PLAYBACK\n", __func__); else dev_dbg(codec->dev, "%s(): CAPTURE\n", __func__); return rc; }
/* * Should only be called when port is inactive. * although can be called multiple times by upper layers. */ static int mxs_saif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); u32 scr, stat; int ret; /* mclk should already be set */ if (!saif->mclk && saif->mclk_in_use) { dev_err(cpu_dai->dev, "set mclk first\n"); return -EINVAL; } stat = __raw_readl(saif->base + SAIF_STAT); if (stat & BM_SAIF_STAT_BUSY) { dev_err(cpu_dai->dev, "error: busy\n"); return -EBUSY; } /* * Set saif clk based on sample rate. * If mclk is used, we also set mclk, if not, saif->mclk is * default 0, means not used. */ ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params)); if (ret) { dev_err(cpu_dai->dev, "unable to get proper clk\n"); return ret; } scr = __raw_readl(saif->base + SAIF_CTRL); scr &= ~BM_SAIF_CTRL_WORD_LENGTH; scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: scr |= BF_SAIF_CTRL_WORD_LENGTH(0); break; case SNDRV_PCM_FORMAT_S20_3LE: scr |= BF_SAIF_CTRL_WORD_LENGTH(4); scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; break; case SNDRV_PCM_FORMAT_S24_LE: scr |= BF_SAIF_CTRL_WORD_LENGTH(8); scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE; break; default: return -EINVAL; } /* Tx/Rx config */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* enable TX mode */ scr &= ~BM_SAIF_CTRL_READ_MODE; } else { /* enable RX mode */ scr |= BM_SAIF_CTRL_READ_MODE; } __raw_writel(scr, saif->base + SAIF_CTRL); return 0; }
static int tegra_bt_sco_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->cpu_dai; struct snd_soc_card *card = rtd->card; struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card); int srate, mclk, min_mclk; int err; srate = params_rate(params); switch (srate) { case 11025: case 22050: case 44100: case 88200: mclk = 11289600; break; case 8000: case 16000: case 32000: case 48000: case 64000: case 96000: mclk = 12288000; break; default: return -EINVAL; } min_mclk = 64 * srate; err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { if (!(machine->util_data.set_mclk % min_mclk)) mclk = machine->util_data.set_mclk; else { dev_err(card->dev, "Can't configure clocks\n"); return err; } } tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1); err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (err < 0) { dev_err(card->dev, "cpu_dai fmt not set\n"); return err; } #ifdef CONFIG_ARCH_TEGRA_2x_SOC err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC2, TEGRA20_DAS_DAP_ID_4); if (err < 0) { dev_err(card->dev, "failed to set dac-dap path\n"); return err; } err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_4, TEGRA20_DAS_DAP_SEL_DAC2); if (err < 0) { dev_err(card->dev, "failed to set dac-dap path\n"); return err; } #endif return 0; }
static int rk29_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; unsigned int pll_out = 0; int ret; DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); /*by Vincent Hsiung for EQ Vol Change*/ #define HW_PARAMS_FLAG_EQVOL_ON 0x21 #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 if (codec_dai->driver->ops->hw_params && ((params->flags == HW_PARAMS_FLAG_EQVOL_ON) || (params->flags == HW_PARAMS_FLAG_EQVOL_OFF))) { ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); } else { /* set codec DAI configuration */ #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); #endif #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM ); #endif if (ret < 0) return ret; /* set cpu DAI configuration */ #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); #endif #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); #endif if (ret < 0) return ret; } switch(params_rate(params)) { case 8000: case 16000: case 24000: case 32000: case 48000: pll_out = 12288000; break; case 11025: case 22050: case 44100: pll_out = 11289600; break; default: DBG("Enter:%s, %d, Error rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); return -EINVAL; break; } DBG("Enter:%s, %d, rate=%d\n", __FUNCTION__, __LINE__, params_rate(params)); /*Set the system clk for codec*/ ret = snd_soc_dai_set_sysclk(codec_dai, 0, pll_out, SND_SOC_CLOCK_IN); if (ret < 0) { DBG("rk29_hw_params_rt3261:failed to set the sysclk for codec side\n"); return ret; } snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1); snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3); DBG("Enter:%s, %d, pll_out/4/params_rate(params) = %d \n", __FUNCTION__, __LINE__, (pll_out/4)/params_rate(params)); return 0; }
static int tegra_wm8903_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_wm8903 *machine = snd_soc_card_get_drvdata(card); int srate, mclk, i2s_daifmt; int err; struct clk *clk_m; int rate; srate = params_rate(params); switch (srate) { case 64000: case 88200: case 96000: mclk = 128 * srate; break; default: mclk = 256 * srate; break; } clk_m = clk_get_sys(NULL, "clk_m"); if (IS_ERR(clk_m)) { dev_err(card->dev, "Can't retrieve clk clk_m\n"); err = PTR_ERR(clk_m); return err; } rate = clk_get_rate(clk_m); printk("extern1 rate=%d\n",rate); #if TEGRA30_I2S_MASTER_PLAYBACK /* FIXME: Codec only requires >= 3MHz if OSR==0 */ while (mclk < 6000000) mclk *= 2; i2s_daifmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; #else mclk = rate; i2s_daifmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; #endif err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk); if (err < 0) { if (!(machine->util_data.set_mclk % mclk)) mclk = machine->util_data.set_mclk; else { dev_err(card->dev, "Can't configure clocks\n"); return err; } } tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1); /* Use DSP mode for mono on Tegra20 */ if ((params_channels(params) != 2) && (machine_is_ventana() || machine_is_harmony() || machine_is_kaen() || machine_is_aebl() || machine_is_eva())) i2s_daifmt |= SND_SOC_DAIFMT_DSP_A; else i2s_daifmt |= SND_SOC_DAIFMT_I2S; err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "codec_dai fmt not set\n"); return err; } err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt); if (err < 0) { dev_err(card->dev, "cpu_dai fmt not set\n"); return err; } err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN); if (err < 0) { dev_err(card->dev, "codec_dai clock not set\n"); return err; } #ifdef CONFIG_ARCH_TEGRA_2x_SOC err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1, TEGRA20_DAS_DAP_ID_1); if (err < 0) { dev_err(card->dev, "failed to set dap-dac path\n"); return err; } err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1, TEGRA20_DAS_DAP_SEL_DAC1); if (err < 0) { dev_err(card->dev, "failed to set dac-dap path\n"); return err; } #endif return 0; }
static int max9867_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct max9867_priv *max9867 = snd_soc_codec_get_drvdata(codec); unsigned int ni_h, ni_l; int value; value = get_ni_value(max9867->sysclk, params_rate(params)); if (value < 0) return value; ni_h = (0xFF00 & value) >> 8; ni_l = 0x00FF & value; /* set up the ni value */ regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH, MAX9867_NI_HIGH_MASK, ni_h); regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW, MAX9867_NI_LOW_MASK, ni_l); if (!max9867->master) { /* * digital pll locks on to any externally supplied LRCLK signal * and also enable rapid lock mode. */ regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKLOW, MAX9867_RAPID_LOCK, MAX9867_RAPID_LOCK); regmap_update_bits(max9867->regmap, MAX9867_AUDIOCLKHIGH, MAX9867_PLL, MAX9867_PLL); } else { unsigned long int bclk_rate, pclk_bclk_ratio; int bclk_value; bclk_rate = params_rate(params) * 2 * params_width(params); pclk_bclk_ratio = max9867->pclk/bclk_rate; switch (params_width(params)) { case 8: case 16: switch (pclk_bclk_ratio) { case 2: bclk_value = MAX9867_IFC1B_PCLK_2; break; case 4: bclk_value = MAX9867_IFC1B_PCLK_4; break; case 8: bclk_value = MAX9867_IFC1B_PCLK_8; break; case 16: bclk_value = MAX9867_IFC1B_PCLK_16; break; default: dev_err(codec->dev, "unsupported sampling rate\n"); return -EINVAL; } break; case 24: bclk_value = MAX9867_IFC1B_24BIT; break; case 32: bclk_value = MAX9867_IFC1B_32BIT; break; default: dev_err(codec->dev, "unsupported sampling rate\n"); return -EINVAL; } regmap_update_bits(max9867->regmap, MAX9867_IFC1B, MAX9867_IFC1B_BCLK_MASK, bclk_value); } return 0; }
static int neo1973_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; unsigned int pll_out = 0, bclk = 0; int ret = 0; unsigned long iis_clkrate; iis_clkrate = s3c24xx_i2s_get_clockrate(); switch (params_rate(params)) { case 8000: case 16000: pll_out = 12288000; break; case 48000: bclk = WM8753_BCLK_DIV_4; pll_out = 12288000; break; case 96000: bclk = WM8753_BCLK_DIV_2; pll_out = 12288000; break; case 11025: bclk = WM8753_BCLK_DIV_16; pll_out = 11289600; break; case 22050: bclk = WM8753_BCLK_DIV_8; pll_out = 11289600; break; case 44100: bclk = WM8753_BCLK_DIV_4; pll_out = 11289600; break; case 88200: bclk = WM8753_BCLK_DIV_2; pll_out = 11289600; break; } /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; /* set the codec system clock for DAC and ADC */ ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, SND_SOC_CLOCK_IN); if (ret < 0) return ret; /* set MCLK division for sample rate */ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, S3C2410_IISMOD_32FS); if (ret < 0) return ret; /* set codec BCLK division for sample rate */ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk); if (ret < 0) return ret; /* set prescaler division for sample rate */ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, S3C24XX_PRESCALE(4, 4)); if (ret < 0) return ret; /* codec PLL input is PCLK/4 */ ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, iis_clkrate / 4, pll_out); if (ret < 0) return ret; return 0; }
static int rk29_aif1_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; unsigned int pll_out = 0; int div_bclk,div_mclk; int ret; struct clk *general_pll; DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); /* set codec DAI configuration */ #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) DBG("Set codec_dai slave\n"); ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); #endif #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); DBG("Set codec_dai master\n"); #endif if (ret < 0) return ret; /* set cpu DAI configuration */ #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) DBG("Set cpu_dai master\n"); ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); #endif #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); DBG("Set cpu_dai slave\n"); #endif if (ret < 0) return ret; switch(params_rate(params)) { case 8000: case 16000: case 24000: case 32000: case 48000: pll_out = 12288000; break; case 11025: case 22050: case 44100: pll_out = 11289600; break; default: DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params)); return -EINVAL; } // DBG("Enter:%s, %d, rate=%d,pll_out = %d\n",__FUNCTION__,__LINE__,params_rate(params),pll_out); general_pll=clk_get(NULL, "general_pll"); if(clk_get_rate(general_pll)>260000000) { div_bclk=(pll_out/4)/params_rate(params)-1; div_mclk=3; } else if(clk_get_rate(general_pll)>130000000) { div_bclk=(pll_out/2)/params_rate(params)-1; div_mclk=1; } else {//96M pll_out=pll_out/4; div_bclk=(pll_out)/params_rate(params)-1; div_mclk=0; } DBG("func is%s,gpll=%ld,pll_out=%d,div_mclk=%d\n",__FUNCTION__,clk_get_rate(general_pll),pll_out,div_mclk); ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0); if(ret < 0) { DBG("rk29_hw_params_wm8994:failed to set the cpu sysclk for codec side\n"); return ret; } snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK,div_bclk); snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, div_mclk); DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params)); if(div_mclk== 3) {//MCLK == 11289600 or 12288000 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, pll_out, 0); if (ret < 0) { DBG("rk29_hw_params_wm8994:failed to set the sysclk for codec side\n"); return ret; } } else { /* set the codec FLL */ ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, pll_out, params_rate(params) * 256); if (ret < 0) { printk("%s: snd_soc_dai_set_pll err =%d\n",__FUNCTION__,ret); return ret; } /* set the codec system clock */ ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1, params_rate(params) * 256, SND_SOC_CLOCK_IN); if (ret < 0) { printk("%s: snd_soc_dai_set_sysclk err =%d\n",__FUNCTION__,ret); return ret; } } return 0; }
static int adau1977_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); unsigned int rate = params_rate(params); unsigned int slot_width; unsigned int ctrl0, ctrl0_mask; unsigned int ctrl1; int mcs, fs; int ret; fs = adau1977_lookup_fs(rate); if (fs < 0) return fs; if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) { mcs = adau1977_lookup_mcs(adau1977, rate, fs); if (mcs < 0) return mcs; } else { mcs = 0; } ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK; ctrl0 = fs; if (adau1977->right_j) { switch (params_width(params)) { case 16: ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT; break; case 24: ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; break; default: return -EINVAL; } ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK; } if (adau1977->master) { switch (params_width(params)) { case 16: ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT; slot_width = 16; break; case 24: case 32: ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT; slot_width = 32; break; default: return -EINVAL; } /* In TDM mode there is a fixed slot width */ if (adau1977->slot_width) slot_width = adau1977->slot_width; if (slot_width == 16) ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16; else ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32; ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL1, ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK | ADAU1977_SAI_CTRL1_BCLKRATE_MASK, ctrl1); if (ret < 0) return ret; } ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_SAI_CTRL0, ctrl0_mask, ctrl0); if (ret < 0) return ret; return regmap_update_bits(adau1977->regmap, ADAU1977_REG_PLL, ADAU1977_PLL_MCS_MASK, mcs); }