static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); int ret = 0; unsigned int fmt = 0; ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); if (ret < 0) { dev_err(rtd->dev, "can't set cpu_dai slot fmt: %d\n", ret); return ret; } fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; ret = snd_soc_dai_set_fmt(rtd->cpu_dai, fmt); if (ret < 0) { dev_err(rtd->dev, "can't set cpu_dai set fmt: %d\n", ret); return ret; } /* The DSP will covert the FE rate to 48k, stereo, 24bits */ rate->min = rate->max = 48000; channels->min = channels->max = 2; /* set SSP2 to 16-bit */ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); return 0; }
static int imx_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->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct imx_priv *priv = &card_priv; unsigned int channels = params_channels(params); unsigned int sample_rate = 44100; int ret = 0; u32 dai_format; unsigned int pll_out; dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, dai_format); if (ret < 0) return ret; /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, channels == 1 ? 0xfffffffe : 0xfffffffc, channels == 1 ? 0xfffffffe : 0xfffffffc, 2, 32); dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBM_CFM; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); if (ret < 0) return ret; sample_rate = params_rate(params); sample_format = params_format(params); if (sample_format == SNDRV_PCM_FORMAT_S24_LE) pll_out = sample_rate * 192; else pll_out = sample_rate * 256; ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL_MCLK, WM8962_FLL_MCLK, priv->sysclk, pll_out); if (ret < 0) pr_err("Failed to start FLL: %d\n", ret); ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_FLL, pll_out, SND_SOC_CLOCK_IN); if (ret < 0) { pr_err("Failed to set SYSCLK: %d\n", ret); return ret; } return 0; }
static int bf5xx_ad193x_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 clk = 0; unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; int ret = 0; switch (params_rate(params)) { case 48000: clk = 24576000; break; } /* set the codec system clock for DAC and ADC */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, SND_SOC_CLOCK_IN); if (ret < 0) return ret; /* set codec DAI slots, 8 channels, all channels are enabled */ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32); if (ret < 0) return ret; /* set cpu DAI channel mapping */ ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map), channel_map, ARRAY_SIZE(channel_map), channel_map); if (ret < 0) return ret; return 0; }
static int eukrea_tlv320_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; int ret; ret = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_OUT); if (ret) { dev_err(cpu_dai->dev, "Failed to set the codec sysclk.\n"); return ret; } snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 0); ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); /* fsl_ssi lacks the set_sysclk ops */ if (ret && ret != -EINVAL) { dev_err(cpu_dai->dev, "Can't set the IMX_SSP_SYS_CLK CPU system clock.\n"); return ret; } return 0; }
static int bf5xx_ad1938_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 ret = 0; ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8); if (ret < 0) return ret; return 0; }
static int imx_si476x_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; u32 channels = params_channels(params); u32 rate = params_rate(params); u32 bclk = rate * channels * 32; int ret = 0; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret) { dev_err(cpu_dai->dev, "failed to set dai fmt\n"); return ret; } ret = snd_soc_dai_set_tdm_slot(cpu_dai, channels == 1 ? 0xfffffffe : 0xfffffffc, channels == 1 ? 0xfffffffe : 0xfffffffc, 2, 32); if (ret) { dev_err(cpu_dai->dev, "failed to set dai tdm slot\n"); return ret; } ret = snd_soc_dai_set_sysclk(cpu_dai, 0, bclk, SND_SOC_CLOCK_OUT); if (ret) dev_err(cpu_dai->dev, "failed to set sysclk\n"); return ret; }
static int imx_3stack_bt_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_link *pcm_link = rtd->dai; struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai; unsigned int channels = params_channels(params); int ret = 0; u32 dai_format; #if BT_SSI_MASTER dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_SYNC; #else dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_SYNC; #endif if (channels == 2) dai_format |= SND_SOC_DAIFMT_TDM; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); if (ret < 0) return ret; /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, channels == 1 ? 0xfffffffe : 0xfffffffc, 2); /* set the SSI system clock as input (unused) */ snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); return 0; }
int asoc_simple_card_init_dai(struct snd_soc_dai *dai, struct asoc_simple_dai *simple_dai) { int ret; if (simple_dai->sysclk) { ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 0); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_sysclk error\n"); return ret; } } if (simple_dai->slots) { ret = snd_soc_dai_set_tdm_slot(dai, simple_dai->tx_slot_mask, simple_dai->rx_slot_mask, simple_dai->slots, simple_dai->slot_width); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); return ret; } } return 0; }
static int saarb_i2s_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; int width = snd_pcm_format_physical_width(params_format(params)); int ret; ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0, PM860X_CLK_DIR_OUT); if (ret < 0) return ret; ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT); 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_CBM_CFM); 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_CBM_CFM); if (ret < 0) return ret; ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width); return ret; }
static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, struct asoc_simple_dai *set) { int ret; if (set->sysclk) { ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_sysclk error\n"); goto err; } } if (set->slots) { ret = snd_soc_dai_set_tdm_slot(dai, 0, 0, set->slots, set->slot_width); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); goto err; } } ret = 0; err: return ret; }
static int bf5xx_ad193x_link_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; /* set the codec system clock for DAC and ADC */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 24576000, SND_SOC_CLOCK_IN); if (ret < 0) return ret; /* set codec DAI slots, 8 channels, all channels are enabled */ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32); if (ret < 0) return ret; ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFF, 0xFF, 8, 32); if (ret < 0) return ret; return 0; }
static int imx_mc13783_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->cpu_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai; int ret; ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 4, 16); if (ret) return ret; ret = snd_soc_dai_set_sysclk(codec_dai, MC13783_CLK_CLIA, 26000000, 0); if (ret) return ret; ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 16); if (ret) return ret; return 0; }
static int imx_3stack_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_link *pcm_link = rtd->dai; struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai; struct snd_soc_dai *codec_dai = pcm_link->codec_dai; unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; int ret = 0; u32 dai_format; #if AK4647_SSI_MASTER dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; #else dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; #endif ssi_mode->sync_mode = 1; if (channels == 1) ssi_mode->network_mode = 0; else ssi_mode->network_mode = 1; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, dai_format); if (ret < 0) return ret; /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, channels == 1 ? 0xfffffffe : 0xfffffffc, 2); /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); if (ret < 0) return ret; /* set the SSI system clock as input (unused) */ snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); snd_soc_dai_set_sysclk(codec_dai, 0, rate, 0); /* set codec BCLK division for sample rate */ snd_soc_dai_set_clkdiv(codec_dai, 0, 0); return 0; }
static int imx_mqs_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; int ret; ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 2, params_width(params)); if (ret) { dev_err(card->dev, "failed to set cpu dai tdm slot: %d\n", ret); return ret; } return 0; }
static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); int ret, bits; /* The DSP will covert the FE rate to 48k, stereo */ rate->min = rate->max = 48000; channels->min = channels->max = 2; if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) || (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) { /* set SSP0 to 16-bit */ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); bits = 16; } else { /* set SSP2 to 24-bit */ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); bits = 24; } /* * Default mode for SSP configuration is TDM 4 slot, override config * with explicit setting to I2S 2ch. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS ); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret; } ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; } return 0; }
static int tm2_late_probe(struct snd_soc_card *card) { struct tm2_machine_priv *priv = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link_component dlc = { 0 }; unsigned int ch_map[] = { 0, 1 }; struct snd_soc_dai *amp_pdm_dai; struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai *aif1_dai; struct snd_soc_dai *aif2_dai; int ret; rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF1].name); aif1_dai = rtd->codec_dai; priv->component = rtd->codec_dai->component; ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); if (ret < 0) { dev_err(aif1_dai->dev, "Failed to set SYSCLK: %d\n", ret); return ret; } rtd = snd_soc_get_pcm_runtime(card, card->dai_link[TM2_DAI_AIF2].name); aif2_dai = rtd->codec_dai; ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); if (ret < 0) { dev_err(aif2_dai->dev, "Failed to set ASYNCCLK: %d\n", ret); return ret; } dlc.of_node = tm2_speaker_amp_dev.codec_of_node; amp_pdm_dai = snd_soc_find_dai(&dlc); if (!amp_pdm_dai) return -ENODEV; /* Set the MAX98504 V/I sense PDM Tx DAI channel mapping */ ret = snd_soc_dai_set_channel_map(amp_pdm_dai, ARRAY_SIZE(ch_map), ch_map, 0, NULL); if (ret < 0) return ret; ret = snd_soc_dai_set_tdm_slot(amp_pdm_dai, 0x3, 0x0, 2, 16); if (ret < 0) return ret; return 0; }
static int bf5xx_ad1836_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; int ret = 0; /* set cpu DAI channel mapping */ ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map), channel_map, ARRAY_SIZE(channel_map), channel_map); if (ret < 0) return ret; ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xFF, 0xFF, 8, 32); if (ret < 0) return ret; return 0; }
static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct cpu_priv *cpu_priv = &priv->cpu_priv; struct device *dev = rtd->card->dev; int ret; priv->sample_rate = params_rate(params); priv->sample_format = params_format(params); /* * If codec-dai is DAI Master and all configurations are already in the * set_bias_level(), bypass the remaining settings in hw_params(). * Note: (dai_fmt & CBM_CFM) includes CBM_CFM and CBM_CFS. */ if ((priv->card.set_bias_level && priv->dai_fmt & SND_SOC_DAIFMT_CBM_CFM) || fsl_asoc_card_is_ac97(priv)) return 0; /* Specific configurations of DAIs starts from here */ ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, cpu_priv->sysclk_id[tx], cpu_priv->sysclk_freq[tx], cpu_priv->sysclk_dir[tx]); if (ret) { dev_err(dev, "failed to set sysclk for cpu dai\n"); return ret; } if (cpu_priv->slot_width) { ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, cpu_priv->slot_width); if (ret) { dev_err(dev, "failed to set TDM slot for cpu dai\n"); return ret; } } return 0; }
static int imx_3stack_surround_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_link *pcm_link = rtd->dai; struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai; struct snd_soc_dai *codec_dai = pcm_link->codec_dai; unsigned int rate = params_rate(params); struct imx_esai *esai_mode = (struct imx_esai *)cpu_dai->private_data; u32 dai_format; if (clk_state.lr_clk_active > 1) return 0; dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; esai_mode->sync_mode = 0; esai_mode->network_mode = 1; /* set codec DAI configuration */ snd_soc_dai_set_fmt(codec_dai, dai_format); /* set cpu DAI configuration */ snd_soc_dai_set_fmt(cpu_dai, dai_format); /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffff, 0xffffffff, 2, 0); /* set the ESAI system clock as input */ snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_IN); /* set codec BCLK division */ snd_soc_dai_set_clkdiv(codec_dai, AK5702_BCLK_CLKDIV, AK5702_BCLK_DIV_32); snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_OUT); snd_soc_dai_set_pll(codec_dai, 1, 0, 12000000, 0); return 0; }
static int eukrea_tlv320_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; int ret; ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret) { pr_err("%s: failed set cpu dai format\n", __func__); return ret; } ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret) { pr_err("%s: failed set codec dai format\n", __func__); return ret; } ret = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_OUT); if (ret) { pr_err("%s: failed setting codec sysclk\n", __func__); return ret; } snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0); ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); if (ret) { pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n"); return ret; } return 0; }
static int imx_3stack_audio_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_link *machine = rtd->dai; struct snd_soc_dai *cpu_dai = machine->cpu_dai; struct snd_soc_dai *codec_dai = machine->codec_dai; struct imx_3stack_priv *priv = &card_priv; unsigned int rate = params_rate(params); struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; int ret = 0; unsigned int channels = params_channels(params); u32 dai_format; /* only need to do this once as capture and playback are sync */ if (priv->hw) return 0; priv->hw = 1; #if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) if ((asrc_ssi_data.output_sample_rate != 0) && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) { unsigned int asrc_input_rate = rate; unsigned int channel = params_channels(params); struct mxc_runtime_data *pcm_data = substream->runtime->private_data; struct asrc_config config; struct mxc_audio_platform_data *plat; struct imx_3stack_priv *priv = &card_priv; int retVal = 0; retVal = asrc_req_pair(channel, &asrc_ssi_data.asrc_index); if (retVal < 0) { pr_err("asrc_req_pair fail\n"); return -1; } config.pair = asrc_ssi_data.asrc_index; config.channel_num = channel; config.input_sample_rate = asrc_input_rate; config.output_sample_rate = asrc_ssi_data.output_sample_rate; config.inclk = INCLK_NONE; config.word_width = 32; plat = priv->pdev->dev.platform_data; if (plat->src_port == 1) config.outclk = OUTCLK_SSI1_TX; else config.outclk = OUTCLK_SSI2_TX; retVal = asrc_config_pair(&config); if (retVal < 0) { pr_err("Fail to config asrc\n"); asrc_release_pair(asrc_ssi_data.asrc_index); return retVal; } rate = asrc_ssi_data.output_sample_rate; pcm_data->asrc_index = asrc_ssi_data.asrc_index; pcm_data->asrc_enable = 1; } #endif snd_soc_dai_set_sysclk(codec_dai, ALC5623_SYSCLK, priv->sysclk, 0); snd_soc_dai_set_sysclk(codec_dai, ALC5623_LRCLK, rate, 0); #if ALC5623_SSI_MASTER dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; #else dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; #endif ssi_mode->sync_mode = 1; if (channels == 1) ssi_mode->network_mode = 0; else ssi_mode->network_mode = 1; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, dai_format); if (ret < 0) return ret; /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, channels == 1 ? 0xfffffffe : 0xfffffffc, channels == 1 ? 0xfffffffe : 0xfffffffc, 2, 32); /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); if (ret < 0) return ret; /* set the SSI system clock as input (unused) */ snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); return 0; }
static int imx_cs42888_surround_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; struct imx_priv *priv = &card_priv; unsigned int rate = params_rate(params); unsigned int lrclk_ratio = 0, i; u32 dai_format = 0; if (priv->hw) return 0; priv->hw = 1; if (priv->codec_mclk & CODEC_CLK_ESAI_HCKT) { for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { if (sr_vals[i].rate == rate) { lrclk_ratio = sr_vals[i].ratio1; break; } } if (i == ARRAY_SIZE(sr_vals)) { dev_err(&priv->pdev->dev, "Unsupported rate %dHz\n", rate); return -EINVAL; } dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; /* set the ESAI system clock as output */ snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL_DIV, priv->mclk_freq, SND_SOC_CLOCK_OUT); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 2); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 2); /* set codec Master clock */ snd_soc_dai_set_sysclk(codec_dai, 0, priv->mclk_freq,\ SND_SOC_CLOCK_IN); } else if (priv->codec_mclk & CODEC_CLK_EXTER_OSC) { for (i = 0; i < ARRAY_SIZE(sr_vals); i++) { if (sr_vals[i].rate == rate) { lrclk_ratio = sr_vals[i].ratio2; break; } } if (i == ARRAY_SIZE(sr_vals)) { dev_err(&priv->pdev->dev, "Unsupported rate %dHz\n", rate); return -EINVAL; } dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL, priv->mclk_freq, SND_SOC_CLOCK_OUT); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 0); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 0); snd_soc_dai_set_sysclk(codec_dai, 0, priv->mclk_freq,\ SND_SOC_CLOCK_IN); } /* set cpu DAI configuration */ snd_soc_dai_set_fmt(cpu_dai, dai_format); /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); /* set the ratio */ snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PSR, 1); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_FP, lrclk_ratio); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PSR, 1); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_FP, lrclk_ratio); /* set codec DAI configuration */ snd_soc_dai_set_fmt(codec_dai, dai_format); return 0; }
static int mop500_ab8500_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 device *dev = rtd->card->dev; unsigned int fmt; int channels, ret = 0, driver_mode, slots; unsigned int sw_codec, sw_cpu; bool is_playback; dev_dbg(dev, "%s: Enter\n", __func__); dev_dbg(dev, "%s: substream->pcm->name = %s\n" "substream->pcm->id = %s.\n" "substream->name = %s.\n" "substream->number = %d.\n", __func__, substream->pcm->name, substream->pcm->id, substream->name, substream->number); /* Ensure configuration consistency between DAIs */ mutex_lock(&mop500_ab8500_params_lock); if (mop500_ab8500_usage) { if (mop500_ab8500_rate != params_rate(params) || mop500_ab8500_channels != params_channels(params)) { mutex_unlock(&mop500_ab8500_params_lock); return -EBUSY; } } else { mop500_ab8500_rate = params_rate(params); mop500_ab8500_channels = params_channels(params); } __set_bit(cpu_dai->id, &mop500_ab8500_usage); mutex_unlock(&mop500_ab8500_params_lock); channels = params_channels(params); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S32_LE: sw_cpu = 32; break; case SNDRV_PCM_FORMAT_S16_LE: sw_cpu = 16; break; default: return -EINVAL; } /* Setup codec depending on driver-mode */ if (channels == 8) driver_mode = DRIVERMODE_CODEC_ONLY; else driver_mode = DRIVERMODE_NORMAL; dev_dbg(dev, "%s: Driver-mode: %s.\n", __func__, (driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY"); /* Setup format */ if (driver_mode == DRIVERMODE_NORMAL) { fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CONT; } else { fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_GATED; } ret = snd_soc_dai_set_fmt(codec_dai, fmt); if (ret < 0) { dev_err(dev, "%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", __func__, ret); return ret; } ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret < 0) { dev_err(dev, "%s: ERROR: snd_soc_dai_set_fmt failed for cpu_dai (ret = %d)!\n", __func__, ret); return ret; } /* Setup TDM-slots */ is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); switch (channels) { case 1: slots = 16; tx_slots = (is_playback) ? TX_SLOT_MONO : 0; rx_slots = (is_playback) ? 0 : RX_SLOT_MONO; break; case 2: slots = 16; tx_slots = (is_playback) ? TX_SLOT_STEREO : 0; rx_slots = (is_playback) ? 0 : RX_SLOT_STEREO; break; case 8: slots = 16; tx_slots = (is_playback) ? TX_SLOT_8CH : 0; rx_slots = (is_playback) ? 0 : RX_SLOT_8CH; break; default: return -EINVAL; } if (driver_mode == DRIVERMODE_NORMAL) sw_codec = sw_cpu; else sw_codec = 20; dev_dbg(dev, "%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, tx_slots, rx_slots); ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots, sw_cpu); if (ret) return ret; dev_dbg(dev, "%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, tx_slots, rx_slots); ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots, sw_codec); if (ret) return ret; return 0; }
int ux500_cg29xx_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; int channels = params_channels(params); int err; pr_debug("%s: Enter.\n", __func__); pr_debug("%s: substream->pcm->name = %s.\n", __func__, substream->pcm->name); pr_debug("%s: substream->pcm->id = %s.\n", __func__, substream->pcm->id); pr_debug("%s: substream->name = %s.\n", __func__, substream->name); pr_debug("%s: substream->number = %d.\n", __func__, substream->number); pr_debug("%s: channels = %d.\n", __func__, channels); pr_debug("%s: DAI-index (Codec): %d\n", __func__, codec_dai->id); pr_debug("%s: DAI-index (Platform): %d\n", __func__, cpu_dai->id); err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS); if (err) { pr_err("%s: snd_soc_dai_set_fmt(codec) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_tdm_slot(codec_dai, 1 << CG29XX_DAI_SLOT0_SHIFT, 1 << CG29XX_DAI_SLOT0_SHIFT, UX500_CG29XX_DAI_SLOTS, UX500_CG29XX_DAI_SLOT_WIDTH); if (err) { pr_err("%s: cg29xx_set_tdm_slot(codec_dai) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_NB_NF); if (err) { pr_err("%s: snd_soc_dai_set_fmt(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_sysclk(cpu_dai, UX500_MSP_MASTER_CLOCK, UX500_CG29XX_MSP_CLOCK_FREQ, 0); if (err) { pr_err("%s: snd_soc_dai_set_sysclk(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } err = snd_soc_dai_set_tdm_slot(cpu_dai, UX500_CG29XX_DAI_ACTIVE_SLOTS, UX500_CG29XX_DAI_ACTIVE_SLOTS, UX500_CG29XX_DAI_SLOTS, UX500_CG29XX_DAI_SLOT_WIDTH); if (err) { pr_err("%s: cg29xx_set_tdm_slot(cpu_dai) failed with %d.\n", __func__, err); goto out_err; } out_err: return err; }
int ux500_ab8500_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 fmt, fmt_if1; int channels, ret = 0, slots, driver_mode; unsigned int codec_slot_width, cpu_slot_width; bool streamIsPlayback; pr_debug("%s: Enter\n", __func__); pr_debug("%s: substream->pcm->name = %s\n" "substream->pcm->id = %s.\n" "substream->name = %s.\n" "substream->number = %d.\n", __func__, substream->pcm->name, substream->pcm->id, substream->name, substream->number); channels = params_channels(params); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S32_LE: cpu_slot_width = 32; break; default: case SNDRV_PCM_FORMAT_S16_LE: cpu_slot_width = 16; break; } /* Setup codec depending on driver-mode */ driver_mode = (channels == 8) ? DRIVERMODE_CODEC_ONLY : DRIVERMODE_NORMAL; pr_debug("%s: Driver-mode: %s.\n", __func__, (driver_mode == DRIVERMODE_NORMAL) ? "NORMAL" : "CODEC_ONLY"); ab8500_audio_set_bit_delay(codec_dai, 1); ux500_msp_dai_set_data_delay(cpu_dai, MSP_DELAY_1); if (driver_mode == DRIVERMODE_NORMAL) { codec_slot_width = cpu_slot_width; ab8500_audio_set_word_length(codec_dai, codec_slot_width); fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CONT; } else { codec_slot_width = 20; ab8500_audio_set_word_length(codec_dai, codec_slot_width); fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_GATED; } ret = snd_soc_dai_set_fmt(codec_dai, fmt); if (ret < 0) { pr_err("%s: ERROR: snd_soc_dai_set_fmt failed for codec_dai (ret = %d)!\n", __func__, ret); return ret; } ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret < 0) { pr_err("%s: ERROR: snd_soc_dai_set_fmt for cpu_dai (ret = %d)!\n", __func__, ret); return ret; } /* Setup TDM-slots */ streamIsPlayback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); switch (channels) { case 1: slots = 8; tx_slots = (streamIsPlayback) ? TX_SLOT_MONO : 0; rx_slots = (streamIsPlayback) ? 0 : RX_SLOT_MONO; break; case 2: slots = 8; tx_slots = (streamIsPlayback) ? TX_SLOT_STEREO : 0; rx_slots = (streamIsPlayback) ? 0 : RX_SLOT_STEREO; break; case 8: slots = 8; tx_slots = (streamIsPlayback) ? TX_SLOT_8CH : 0; rx_slots = (streamIsPlayback) ? 0 : RX_SLOT_8CH; break; default: return -EINVAL; } pr_debug("%s: CPU-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, tx_slots, rx_slots); ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_slots, rx_slots, slots, cpu_slot_width); if (ret) return ret; pr_debug("%s: CODEC-DAI TDM: TX=0x%04X RX=0x%04x\n", __func__, tx_slots, rx_slots); ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_slots, rx_slots, slots, codec_slot_width); if (ret) return ret; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { pr_debug("%s: Setup IF1 for FM-radio.\n", __func__); fmt_if1 = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_I2S; ret = ab8500_audio_setup_if1(codec_dai->codec, fmt_if1, 16, 1); if (ret) return ret; } return 0; }
static int imx_3stack_surround_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 rate = params_rate(params); u32 dai_format; unsigned int lrclk_ratio = 0; if (hw_state.hw) return 0; hw_state.hw = 1; if (cpu_is_mx53()) { switch (rate) { case 32000: lrclk_ratio = 3; break; case 48000: lrclk_ratio = 3; break; case 64000: lrclk_ratio = 1; break; case 96000: lrclk_ratio = 1; break; case 128000: lrclk_ratio = 1; break; case 44100: lrclk_ratio = 3; break; case 88200: lrclk_ratio = 1; break; case 176400: lrclk_ratio = 0; break; case 192000: lrclk_ratio = 0; break; default: pr_info("Rate not support.\n"); return -EINVAL;; } } else if (cpu_is_mx6q()) { switch (rate) { case 32000: lrclk_ratio = 5; break; case 48000: lrclk_ratio = 5; break; case 64000: lrclk_ratio = 2; break; case 96000: lrclk_ratio = 2; break; case 128000: lrclk_ratio = 2; break; case 44100: lrclk_ratio = 5; break; case 88200: lrclk_ratio = 2; break; case 176400: lrclk_ratio = 0; break; case 192000: lrclk_ratio = 0; break; default: pr_info("Rate not support.\n"); return -EINVAL;; } } dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; /* set cpu DAI configuration */ snd_soc_dai_set_fmt(cpu_dai, dai_format); /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); /* set the ESAI system clock as output */ if (cpu_is_mx53()) { snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL, mclk_freq, SND_SOC_CLOCK_OUT); } else if (cpu_is_mx6q()) { snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL_DIV, mclk_freq, SND_SOC_CLOCK_OUT); } /* set the ratio */ snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PSR, 1); if (cpu_is_mx53()) snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 0); else if (cpu_is_mx6q()) snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 2); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_FP, lrclk_ratio); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PSR, 1); if (cpu_is_mx53()) snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 0); else if (cpu_is_mx6q()) snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 2); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_FP, lrclk_ratio); /* set codec DAI configuration */ snd_soc_dai_set_fmt(codec_dai, dai_format); /* set codec Master clock */ snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, SND_SOC_CLOCK_IN); return 0; }
/* * Magician uses SSP port for playback. */ static int magician_playback_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; unsigned int acps, acds, width, rate; unsigned int div4 = PXA_SSP_CLK_SCDB_4; int ret = 0; rate = params_rate(params); width = snd_pcm_format_physical_width(params_format(params)); /* * rate = SSPSCLK / (2 * width(16 or 32)) * SSPSCLK = (ACPS / ACDS) / SSPSCLKDIV(div4 or div1) */ switch (params_rate(params)) { case 8000: /* off by a factor of 2: bug in the PXA27x audio clock? */ acps = 32842000; switch (width) { case 16: /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */ acds = PXA_SSP_CLK_AUDIO_DIV_16; break; default: /* 32 */ /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */ acds = PXA_SSP_CLK_AUDIO_DIV_8; } break; case 11025: acps = 5622000; switch (width) { case 16: /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */ acds = PXA_SSP_CLK_AUDIO_DIV_4; break; default: /* 32 */ /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */ acds = PXA_SSP_CLK_AUDIO_DIV_2; } break; case 22050: acps = 5622000; switch (width) { case 16: /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */ acds = PXA_SSP_CLK_AUDIO_DIV_2; break; default: /* 32 */ /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */ acds = PXA_SSP_CLK_AUDIO_DIV_1; } break; case 44100: acps = 5622000; switch (width) { case 16: /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */ acds = PXA_SSP_CLK_AUDIO_DIV_2; break; default: /* 32 */ /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */ acds = PXA_SSP_CLK_AUDIO_DIV_1; } break; case 48000: acps = 12235000; switch (width) { case 16: /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */ acds = PXA_SSP_CLK_AUDIO_DIV_2; break; default: /* 32 */ /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */ acds = PXA_SSP_CLK_AUDIO_DIV_1; } break; case 96000: default: acps = 12235000; switch (width) { case 16: /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */ acds = PXA_SSP_CLK_AUDIO_DIV_1; break; default: /* 32 */ /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */ acds = PXA_SSP_CLK_AUDIO_DIV_2; div4 = PXA_SSP_CLK_SCDB_1; break; } break; } /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 0, 1, width); if (ret < 0) return ret; /* set audio clock as clock source */ ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, SND_SOC_CLOCK_OUT); if (ret < 0) return ret; /* set the SSP audio system clock ACDS divider */ ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); if (ret < 0) return ret; /* set the SSP audio system clock SCDB divider4 */ ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_SCDB, div4); if (ret < 0) return ret; /* set SSP audio pll clock */ ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, acps); if (ret < 0) return ret; return 0; }
static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { int ret; struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); /* The DSP will covert the FE rate to 48k, stereo, 24bits */ rate->min = rate->max = 48000; channels->min = channels->max = 2; if ((cht_rt5645_quirk & CHT_RT5645_SSP0_AIF1) || (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) { /* set SSP0 to 16-bit */ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); /* * Default mode for SSP configuration is TDM 4 slot, override config * with explicit setting to I2S 2ch 16-bit. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS ); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret; } ret = snd_soc_dai_set_fmt(rtd->codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS ); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret; } ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; } } else { /* set SSP2 to 24-bit */ params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); /* * Default mode for SSP configuration is TDM 4 slot */ ret = snd_soc_dai_set_fmt(rtd->codec_dai, SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) { dev_err(rtd->dev, "can't set format to TDM %d\n", ret); return ret; } /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0xF, 0xF, 4, 24); if (ret < 0) { dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret); return ret; } } return 0; }
static int imx_3stack_audio_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_link *machine = rtd->dai; struct snd_soc_dai *cpu_dai = machine->cpu_dai; struct snd_soc_dai *codec_dai = machine->codec_dai; struct imx_3stack_priv *priv = &machine_priv; int ret = 0; int i, found = 0; snd_pcm_format_t format = params_format(params); unsigned int rate = params_rate(params); unsigned int channels = params_channels(params); struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data; u32 dai_format; /* only need to do this once as capture and playback are sync */ if (priv->lr_clk_active > 1) return 0; /* find the correct audio parameters */ for (i = 0; i < ARRAY_SIZE(wm8350_audio); i++) { if (rate == wm8350_audio[i].rate && format == wm8350_audio[i].format && channels == wm8350_audio[i].channels) { found = 1; break; } } if (!found) { printk(KERN_ERR "%s: invalid params\n", __func__); return -EINVAL; } #if WM8350_SSI_MASTER /* codec FLL input is 32768 kHz from MCLK */ snd_soc_dai_set_pll(codec_dai, 0, 32768, wm8350_audio[i].sysclk); #else /* codec FLL input is rate from DAC LRC */ snd_soc_dai_set_pll(codec_dai, 0, rate, wm8350_audio[i].sysclk); #endif #if WM8350_SSI_MASTER dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM; ssi_mode->sync_mode = 1; if (channels == 1) ssi_mode->network_mode = 0; else ssi_mode->network_mode = 1; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, dai_format); if (ret < 0) return ret; /* set cpu DAI configuration */ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { dai_format &= ~SND_SOC_DAIFMT_INV_MASK; /* Invert frame to switch mic from right channel to left */ dai_format |= SND_SOC_DAIFMT_NB_IF; } /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, channels == 1 ? 0xfffffffe : 0xfffffffc, channels); ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); if (ret < 0) return ret; /* set 32KHZ as the codec system clock for DAC and ADC */ snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_32K, wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN); #else dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, dai_format); if (ret < 0) return ret; /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, channels == 1 ? 0xfffffffe : 0xfffffffc, channels); /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format); if (ret < 0) return ret; /* set DAC LRC as the codec system clock for DAC and ADC */ snd_soc_dai_set_sysclk(codec_dai, WM8350_MCLK_SEL_PLL_DAC, wm8350_audio[i].sysclk, SND_SOC_CLOCK_IN); #endif /* set the SSI system clock as input (unused) */ snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN); /* set codec BCLK division for sample rate */ snd_soc_dai_set_clkdiv(codec_dai, WM8350_BCLK_CLKDIV, wm8350_audio[i].bclkdiv); /* DAI is synchronous and clocked with DAC LRCLK & ADC LRC */ snd_soc_dai_set_clkdiv(codec_dai, WM8350_DACLR_CLKDIV, wm8350_audio[i].lr_rate); snd_soc_dai_set_clkdiv(codec_dai, WM8350_ADCLR_CLKDIV, wm8350_audio[i].lr_rate); /* now configure DAC and ADC clocks */ snd_soc_dai_set_clkdiv(codec_dai, WM8350_DAC_CLKDIV, wm8350_audio[i].clkdiv); snd_soc_dai_set_clkdiv(codec_dai, WM8350_ADC_CLKDIV, wm8350_audio[i].clkdiv); return 0; }
static int imx_3stack_surround_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_link *pcm_link = rtd->dai; struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai; struct snd_soc_dai *codec_dai = pcm_link->codec_dai; unsigned int rate = params_rate(params); u32 dai_format; unsigned int lrclk_ratio = 0; #if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) unsigned int channel = params_channels(params); #endif struct imx_esai *esai_mode = (struct imx_esai *)cpu_dai->private_data; if (clk_state.lr_clk_active > 1) return 0; #if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE) if (asrc_esai_data.output_sample_rate >= 32000) { unsigned int asrc_input_rate = rate; struct mxc_runtime_data *pcm_data = substream->runtime->private_data; struct asrc_config config; int retVal = 0;; retVal = asrc_req_pair(channel, &asrc_esai_data.asrc_index); if (retVal < 0) { pr_err("Fail to request asrc pair\n"); return -1; } config.pair = asrc_esai_data.asrc_index; config.channel_num = channel; config.input_sample_rate = asrc_input_rate; config.output_sample_rate = asrc_esai_data.output_sample_rate; config.inclk = INCLK_NONE; config.word_width = 32; config.outclk = OUTCLK_ESAI_TX; retVal = asrc_config_pair(&config); if (retVal < 0) { pr_err("Fail to config asrc\n"); asrc_release_pair(asrc_esai_data.asrc_index); return retVal; } rate = asrc_esai_data.output_sample_rate; pcm_data->asrc_index = asrc_esai_data.asrc_index; pcm_data->asrc_enable = 1; } #endif switch (rate) { case 32000: lrclk_ratio = 3; break; case 48000: lrclk_ratio = 3; break; case 64000: lrclk_ratio = 1; break; case 96000: lrclk_ratio = 1; break; case 128000: lrclk_ratio = 1; break; case 44100: lrclk_ratio = 3; break; case 88200: lrclk_ratio = 1; break; case 176400: lrclk_ratio = 0; break; case 192000: lrclk_ratio = 0; break; default: pr_info("Rate not support.\n"); return -EINVAL;; } dai_format = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; esai_mode->sync_mode = 0; esai_mode->network_mode = 1; /* set cpu DAI configuration */ snd_soc_dai_set_fmt(cpu_dai, dai_format); /* set i.MX active slot mask */ snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); /* set the ESAI system clock as output */ snd_soc_dai_set_sysclk(cpu_dai, ESAI_CLK_EXTAL, mclk_freq, SND_SOC_CLOCK_OUT); /* set the ratio */ snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PSR, 1); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_PM, 0); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_TX_DIV_FP, lrclk_ratio); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PSR, 1); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_PM, 0); snd_soc_dai_set_clkdiv(cpu_dai, ESAI_RX_DIV_FP, lrclk_ratio); /* set codec DAI configuration */ snd_soc_dai_set_fmt(codec_dai, dai_format); /* set codec Master clock */ snd_soc_dai_set_sysclk(codec_dai, 0, mclk_freq, SND_SOC_CLOCK_IN); return 0; }