static long asrc_ioctl_req_pair(struct asrc_pair_params *params, void __user *user) { struct asrc_req req; long ret; ret = copy_from_user(&req, user, sizeof(req)); if (ret) { dev_err(asrc->dev, "failed to get req from user space: %ld\n", ret); return ret; } ret = asrc_req_pair(req.chn_num, &req.index); if (ret) { dev_err(asrc->dev, "failed to request pair: %ld\n", ret); return ret; } params->pair_hold = 1; params->index = req.index; params->channel_nums = req.chn_num; ret = copy_to_user(user, &req, sizeof(req)); if (ret) { dev_err(asrc->dev, "failed to send req to user space: %ld\n", ret); return ret; } return 0; }
static int config_asrc(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { unsigned int rate = params_rate(params); unsigned int channel = params_channels(params); unsigned int wordwidth = get_format_width(params); struct imx_pcm_runtime_data *pcm_data = substream->runtime->private_data; struct asrc_config config = {0}; int ret = 0; if (rate <= 32000 || rate == asrc_esai_data.output_sample_rate) return -EINVAL; if (channel != 2) return -EINVAL; if (wordwidth != 24) return -EINVAL; ret = asrc_req_pair(channel, &asrc_esai_data.asrc_index); if (ret < 0) { pr_err("Fail to request asrc pair\n"); asrc_release_pair(asrc_esai_data.asrc_index); asrc_finish_conv(asrc_esai_data.asrc_index); return -EINVAL; } config.pair = asrc_esai_data.asrc_index; config.channel_num = channel; config.input_sample_rate = rate; config.output_sample_rate = asrc_esai_data.output_sample_rate; config.inclk = OUTCLK_ASRCK1_CLK; config.word_width = wordwidth; config.outclk = OUTCLK_ESAI_TX; ret = asrc_config_pair(&config); if (ret < 0) { pr_err("Fail to config asrc\n"); asrc_release_pair(asrc_esai_data.asrc_index); asrc_finish_conv(asrc_esai_data.asrc_index); return ret; } pcm_data->asrc_index = asrc_esai_data.asrc_index; pcm_data->asrc_enable = 1; return 0; }
static int config_asrc(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { unsigned int rate = params_rate(params); unsigned int channel = params_channels(params); struct imx_pcm_runtime_data *iprtd = substream->runtime->private_data; struct asrc_config config = {0}; int ret = 0; if ((channel != 2) && (channel != 4) && (channel != 6)) return -EINVAL; ret = asrc_req_pair(channel, &iprtd->asrc_index); if (ret < 0) { pr_err("Fail to request asrc pair\n"); return -EINVAL; } config.input_word_width = get_asrc_input_width(params); config.output_word_width = iprtd->p2p->p2p_width; config.pair = iprtd->asrc_index; config.channel_num = channel; config.input_sample_rate = rate; config.output_sample_rate = iprtd->p2p->p2p_rate; config.inclk = INCLK_NONE; config.outclk = OUTCLK_ESAI_TX; ret = asrc_config_pair(&config); if (ret < 0) { pr_err("Fail to config asrc\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); 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; }
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; }