예제 #1
0
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;
}
예제 #2
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_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(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
				SNDRV_PCM_HW_PARAM_FIRST_MASK],
				SNDRV_PCM_FORMAT_S16_LE);
	return 0;
}
예제 #3
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(&params->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;
}
예제 #4
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(&params->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(&params->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(&params->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(&params->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;
}
예제 #7
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(&params->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(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
	                            SNDRV_PCM_HW_PARAM_FIRST_MASK],
	                            SNDRV_PCM_FORMAT_S16_LE);
	return 0;
}
예제 #9
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;
}
예제 #10
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(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
				    SNDRV_PCM_HW_PARAM_FIRST_MASK],
				    SNDRV_PCM_FORMAT_S16_LE);
	return 0;
}
예제 #11
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;
}
예제 #12
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(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
				SNDRV_PCM_HW_PARAM_FIRST_MASK]);
	snd_mask_reset(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
			SNDRV_PCM_HW_PARAM_FIRST_MASK],
			min_mask);
	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
				    SNDRV_PCM_HW_PARAM_FIRST_MASK],
		     val);
	return 0;
}
예제 #13
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(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
				SNDRV_PCM_HW_PARAM_FIRST_MASK],
				SNDRV_PCM_FORMAT_S24_LE);
	return 0;
}
예제 #14
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;
}
예제 #15
0
파일: msm8x60.c 프로젝트: veirs/UbuntuTouch
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(&params.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, &params, codec_dai);
	}

	return rc;
}