static void compr_config_hw_params(struct snd_pcm_hw_params *params, struct snd_compr_params *compr_params) { u64 fmt; int acodec_rate = 48000; pr_debug("%s\n", __func__); fmt = ffs(SNDRV_PCM_FMTBIT_S16_LE) - 1; snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt); hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min = 16; hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS)->min = 32; hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min = 2; #ifdef CONFIG_SND_ESA_SA_EFFECT acodec_rate = esa_compr_get_sample_rate(); if (!acodec_rate) acodec_rate = 48000; #endif pr_info("%s input_SR %d PCM_HW_PARAM_RATE %d \n", __func__, compr_params->codec.sample_rate, acodec_rate); hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = acodec_rate; }
static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); unsigned int be_id = rtd->dai_link->be_id; switch (be_id) { case OMAP_ABE_DAI_BT_VX: channels->min = 2; rate->min = rate->max = 8000; break; case OMAP_ABE_DAI_MM_FM: channels->min = 2; rate->min = rate->max = 48000; break; case OMAP_ABE_DAI_MODEM: break; default: return -EINVAL; } snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S16_LE); return 0; }
static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); unsigned int be_id = rtd->dai_link->be_id; unsigned int threshold; switch (be_id) { case OMAP_ABE_DAI_MM_FM: channels->min = 2; threshold = 2; break; case OMAP_ABE_DAI_BT_VX: channels->min = 1; threshold = 1; break; default: threshold = 1; break; } snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S16_LE); omap_mcbsp_set_tx_threshold(cpu_dai->id, threshold); omap_mcbsp_set_rx_threshold(cpu_dai->id, threshold); return 0; }
static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct imx_priv *priv = &card_priv; hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min = priv->fe_output_rate; hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max = priv->fe_output_rate; snd_mask_none(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT)); if (priv->fe_output_width == 16) snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), SNDRV_PCM_FORMAT_S16_LE); else snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), SNDRV_PCM_FORMAT_S24_LE); return 0; }
static int dmic_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S32_LE); return 0; }
static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned int be_id; unsigned int threshold; unsigned int val, min_mask; DBG ("%s: Entered \n", __func__); //DBG ("%s: CPU DAI %s BE_ID %d\n", __func__, cpu_dai->name, rtd->dai_link->be_id); be_id = rtd->dai_link->be_id; switch (be_id) { case OMAP_ABE_DAI_MM_FM: channels->min = 2; threshold = 2; val = SNDRV_PCM_FORMAT_S16_LE; break; case OMAP_ABE_DAI_BT_VX: channels->min = 1; threshold = 1; val = SNDRV_PCM_FORMAT_S16_LE; break; default: threshold = 1; val = SNDRV_PCM_FORMAT_S16_LE; break; } min_mask = snd_mask_min(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK]); //DBG ("%s: Returned min_mask 0x%x Format %x\n", __func__, min_mask, val); snd_mask_reset(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], min_mask); //DBG ("%s: Returned min_mask 0x%x Format %x\n", __func__, min_mask, val); snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], val); omap_mcbsp_set_tx_threshold(cpu_dai->id, threshold); omap_mcbsp_set_rx_threshold(cpu_dai->id, threshold); DBG ("%s: Exiting \n", __func__); return 0; }
static int dmic_be_hw_params_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); /* The ABE will covert the FE rate to 96k */ rate->min = rate->max = 96000; snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S32_LE); return 0; }
static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); unsigned int be_id = rtd->dai_link->be_id; if (be_id == OMAP_ABE_DAI_MM_FM || be_id == OMAP_ABE_DAI_BT_VX) channels->min = 2; snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S16_LE); return 0; }
static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_interval *rate; struct snd_mask *mask; rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); rate->max = rate->min = priv->asrc_rate; mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); snd_mask_none(mask); snd_mask_set(mask, priv->asrc_format); return 0; }
static int broadwell_ssp0_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); /* The ADSP will covert the FE rate to 48k, stereo */ rate->min = rate->max = 48000; channels->min = channels->max = 2; /* set SSP0 to 16 bit */ snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S16_LE); return 0; }
static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct imx_priv *priv = &card_priv; struct snd_interval *rate; struct snd_mask *mask; if (!priv->asrc_pdev) return -EINVAL; rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); rate->max = rate->min = priv->asrc_rate; mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); snd_mask_none(mask); snd_mask_set(mask, priv->asrc_format); return 0; }
static int mcbsp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); unsigned int val, min_mask; val = SNDRV_PCM_FORMAT_S16_LE; min_mask = snd_mask_min(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK]); snd_mask_reset(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], min_mask); snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], val); return 0; }
static int merr_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); pr_debug("Invoked %s for dailink %s\n", __func__, rtd->dai_link->name); /* The DSP will convert the FE rate to 48k, stereo, 24bits */ rate->min = rate->max = 48000; channels->min = channels->max = 2; /* set SSP2 to 24-bit */ snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S24_LE); return 0; }
int ksnd_pcm_set_params(ksnd_pcm_t *pcm, int nrchannels, int sampledepth, int samplerate, int periodsize, int buffersize) { snd_pcm_substream_t *substream = pcm->substream; snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_hw_params_t *hw_params = NULL; snd_pcm_sw_params_t *sw_params = NULL; int err; int format; snd_mask_t mask; int i; void *hwbuf; err = ksnd_pcm_hw_params_malloc(&hw_params); if (0 != err) goto failure; sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL); if (!sw_params) { err = -ENOMEM; goto failure; } switch (sampledepth) { case 16: format = SNDRV_PCM_FORMAT_S16_LE; break; case 24: sampledepth = 32; /*FALLTHRU*/ case 32: format = SNDRV_PCM_FORMAT_S32_LE; break; default: snd_printd("%s Unsupported sampledepth %d\n", __FUNCTION__, sampledepth); err = -EINVAL; goto failure; } err = ksnd_pcm_hw_params_any(pcm, hw_params); if (snd_BUG_ON(err < 0)) goto failure; _snd_pcm_hw_param_setinteger(hw_params, SNDRV_PCM_HW_PARAM_PERIODS); _snd_pcm_hw_param_min(hw_params, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); snd_mask_none(&mask); snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); err = snd_pcm_hw_param_mask(substream, hw_params, SNDRV_PCM_HW_PARAM_ACCESS, &mask); if (err < 0) { err = -EINVAL; goto failure; } err = snd_pcm_hw_param_set(substream, hw_params, SNDRV_PCM_HW_PARAM_RATE, samplerate, 0); if (snd_BUG_ON(err < 0)) goto failure; err = snd_pcm_hw_param_near(substream, hw_params, SNDRV_PCM_HW_PARAM_CHANNELS, nrchannels, NULL); if (snd_BUG_ON(err < 0)) goto failure; err = snd_pcm_hw_param_near(substream, hw_params, SNDRV_PCM_HW_PARAM_FORMAT, format, 0); if (snd_BUG_ON(err < 0)) goto failure; err = snd_pcm_hw_param_near(substream, hw_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, periodsize, NULL); if (snd_BUG_ON(err < 0)) goto failure; err = snd_pcm_hw_param_near(substream, hw_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, buffersize, NULL); if (snd_BUG_ON(err < 0)) goto failure; _ksnd_pcm_drop(substream); /*now we re-use the 61937 control to enable the HW sync mechanism */ if (0 != (err = ksnd_pcm_hw_params(pcm, hw_params) < 0)) { snd_printd("HW_PARAMS failed: for %d:%d code is %i\n", substream->pcm->card->number, substream->pcm->device, err); goto failure; } memset(sw_params, 0, sizeof(*sw_params)); sw_params->start_threshold = (runtime->buffer_size - (runtime->period_size * 2)); sw_params->stop_threshold = runtime->buffer_size; sw_params->period_step = 1; sw_params->sleep_min = 0; sw_params->avail_min = runtime->period_size; sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE; sw_params->silence_threshold = runtime->period_size; sw_params->silence_size = runtime->period_size; if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { snd_printd("SW_PARAMS failed: for %d:%d code is %i\n", substream->pcm->card->number, substream->pcm->device, err); goto failure; } if ((err = ksnd_pcm_prepare(pcm)) < 0) goto failure; if (pcm->hwareas[0].addr) iounmap(pcm->hwareas[0].addr); hwbuf = ioremap_nocache(runtime->dma_addr, runtime->dma_bytes); for (i = 0; i < nrchannels; i++) { pcm->hwareas[i].addr = hwbuf; pcm->hwareas[i].first = i * sampledepth; pcm->hwareas[i].step = nrchannels * sampledepth; } nrchannels = _ksnd_pcm_hw_param_value(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS, 0); samplerate = _ksnd_pcm_hw_param_value(hw_params, SNDRV_PCM_HW_PARAM_RATE, 0); periodsize = _ksnd_pcm_hw_param_value(hw_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 0); buffersize = _ksnd_pcm_hw_param_value(hw_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0); printk(KERN_DEBUG "ksound: Set parameters for hw:%d,%d to %d x %dhz with period %d (of %d)\n", substream->pcm->card->number, substream->pcm->device, nrchannels, samplerate, periodsize, buffersize); err = 0; failure: if (hw_params) ksnd_pcm_hw_params_free(hw_params); if (sw_params) kfree(sw_params); return err; }
static int configure_wm_hw(struct msm_snddev_info *dev_info) { int rc = 0; /* if device is internal pcm, then configure wolfson codec */ if (dev_info->copp_id == PRIMARY_I2S_RX || dev_info->copp_id == PRIMARY_I2S_TX) { struct snd_pcm_substream substream; struct snd_pcm_hw_params params; struct snd_soc_dai *codec_dai; struct wm8994_priv *wm8994; int fll = 0, fll_sysclk = 0, fll_rate = 0; int aifclk = 0; int bclk_rate = 0; static int bclk_rate_tx = 0, bclk_rate_rx = 0; if (dev_info->capability & SNDDEV_CAP_RX) { codec_dai = &wm8994_dai[0]; substream.stream = SNDRV_PCM_STREAM_PLAYBACK; fll = WM8994_FLL1; fll_sysclk = WM8994_SYSCLK_FLL1; aifclk = WM8994_AIF1_CLOCKING_1; } else { codec_dai = &wm8994_dai[1]; substream.stream = SNDRV_PCM_STREAM_CAPTURE; fll = WM8994_FLL2; fll_sysclk = WM8994_SYSCLK_FLL2; aifclk = WM8994_AIF2_CLOCKING_1; } wm8994 = snd_soc_codec_get_drvdata (codec_dai->codec); params.intervals[SNDRV_PCM_HW_PARAM_CHANNELS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = dev_info->channel_mode; params.intervals[SNDRV_PCM_HW_PARAM_CHANNELS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].max = dev_info->channel_mode; params.intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].min = dev_info->sample_rate; params.intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL].max = dev_info->sample_rate; snd_mask_set(¶ms.masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK], SNDRV_PCM_FORMAT_S16_LE); /* Set fll rate by multiplying 2 channels even if its mono * aifclk rates need to be atleast 256*fs, 1 channel would make it 128*fs * also, must be >= 4.096Mhz and <= 12.5Mhz, refer to datasheet. */ bclk_rate = dev_info->sample_rate * WM_CHANNELS * WM_BITS; if (dev_info->capability & SNDDEV_CAP_RX) { if (bclk_rate_rx == bclk_rate) { pr_info("aif1 codec rates are already configured, just return\n"); return rc; } bclk_rate_rx = bclk_rate; } else { if (bclk_rate_tx == bclk_rate) { pr_info("aif2 codec rates are already configured, just return\n"); return rc; } bclk_rate_tx = bclk_rate; } fll_rate = bclk_rate * WM_FLL_MULT; if (fll_rate < WM_FLL_MIN_RATE) fll_rate = WM_FLL_MIN_RATE; /* aif clocks are disabled when reconfiguring fll and bclk rates */ rc = snd_soc_dai_set_pll(codec_dai, fll, WM8994_FLL_SRC_BCLK, bclk_rate, fll_rate); if (rc < 0) { pr_err("Failed to set DAI FLL to rate %d: ret %d\n", WM_FLL_MULT * bclk_rate, rc); return rc; } rc = snd_soc_dai_set_sysclk(codec_dai, fll_sysclk, fll_rate, 0); if (rc < 0) { pr_err("Failed to set sysclk: ret %d\n", rc); return rc; } wm8994_hw_params(&substream, ¶ms, codec_dai); } return rc; }