Example #1
0
static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
				 snd_pcm_hw_param_t var, unsigned int val,
				 int dir)
{
	int changed;
	if (hw_is_mask(var)) {
		struct snd_mask *m = hw_param_mask(params, var);
		if (val == 0 && dir < 0) {
			changed = -EINVAL;
			snd_mask_none(m);
		} else {
			if (dir > 0)
				val++;
			else if (dir < 0)
				val--;
			changed = snd_mask_refine_set(
					hw_param_mask(params, var), val);
		}
	} else if (hw_is_interval(var)) {
		struct snd_interval *i = hw_param_interval(params, var);
		if (val == 0 && dir < 0) {
			changed = -EINVAL;
			snd_interval_none(i);
		} else if (dir == 0)
			changed = snd_interval_refine_set(i, val);
		else {
			struct snd_interval t;
			t.openmin = 1;
			t.openmax = 1;
			t.empty = 0;
			t.integer = 0;
			if (dir < 0) {
				t.min = val - 1;
				t.max = val;
			} else {
				t.min = val;
				t.max = val+1;
			}
			changed = snd_interval_refine(i, &t);
		}
	} else {
		return -EINVAL;
	}
	if (changed) {
		params->cmask |= 1 << var;
		params->rmask |= 1 << var;
	}
	return changed;
}
Example #2
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 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;
}
Example #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;
	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;
}
Example #5
0
static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
								 snd_pcm_hw_param_t var, unsigned int val,
								 int dir)
{
	int changed;
	int open = 0;
	if (dir)
	{
		if (dir < 0)
		{
			open = 1;
		}
		else if (dir > 0)
		{
			open = 1;
			val++;
		}
	}
	if (hw_is_mask(var))
	{
		if (val == 0 && open)
		{
			snd_mask_none(hw_param_mask(params, var));
			changed = -EINVAL;
		}
		else
			changed = snd_mask_refine_max(hw_param_mask(params, var),
										  val - !!open);
	}
	else if (hw_is_interval(var))
		changed = snd_interval_refine_max(hw_param_interval(params, var),
										  val, open);
	else
		return -EINVAL;
	if (changed)
	{
		params->cmask |= 1 << var;
		params->rmask |= 1 << var;
	}
	return changed;
}
Example #6
0
/*
 * here goes a really tricky part; hw_refine falls back to ACCESS_RW_* type
 * when ACCESS_MMAP_* isn't supported by the hardware.
 */
static int snd_pcm_mmap_emul_hw_refine(snd_pcm_t *pcm,
				       snd_pcm_hw_params_t *params)
{
	mmap_emul_t *map = pcm->private_data;
	int err = 0;
	snd_pcm_access_mask_t oldmask =
		*snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS);
	snd_pcm_access_mask_t mask;
	const snd_mask_t *pmask;

	snd_mask_none(&mask);
	err = snd_pcm_hw_refine(map->gen.slave, params);
	if (err < 0) {
		snd_pcm_hw_params_t new = *params;

		/* try to use RW_* */
		if (snd_pcm_access_mask_test(&oldmask,
					     SND_PCM_ACCESS_MMAP_INTERLEAVED) &&
		    !snd_pcm_access_mask_test(&oldmask,
					      SND_PCM_ACCESS_RW_INTERLEAVED))
			snd_pcm_access_mask_set(&mask,
						SND_PCM_ACCESS_RW_INTERLEAVED);
		if (snd_pcm_access_mask_test(&oldmask,
					     SND_PCM_ACCESS_MMAP_NONINTERLEAVED) &&
		    !snd_pcm_access_mask_test(&oldmask,
					      SND_PCM_ACCESS_RW_NONINTERLEAVED))
			snd_pcm_access_mask_set(&mask,
						SND_PCM_ACCESS_RW_NONINTERLEAVED);
		if (snd_pcm_access_mask_empty(&mask))
			return err;
		pmask = snd_pcm_hw_param_get_mask(&new,
						  SND_PCM_HW_PARAM_ACCESS);
		*(snd_mask_t *)pmask = mask;
		err = snd_pcm_hw_refine(map->gen.slave, &new);
		if (err < 0)
			return err;
		*params = new;
	}
Example #7
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;
}