Example #1
0
/**
 * \brief _ksnd_pcm_hw_param_value
 *
 * Implementation is copied directly from Linux's not-exported-to-modules
 * snd_pcm_hw_param_value function.
 *
 * \param params the hw_params instance
 * \param var    parameter to retrieve
 * \param dir    pointer to the direction (-1,0,1) or NULL
 *
 * \return Return the value for field PAR if it's fixed in
 *         configuration space defined by PARAMS. Return -EINVAL otherwise
 */
static int _ksnd_pcm_hw_param_value(const ksnd_pcm_hw_params_t *params,
									snd_pcm_hw_param_t var, int *dir)
{
	if (hw_is_mask(var))
	{
		const struct snd_mask *mask = hw_param_mask_c(params, var);
		if (!snd_mask_single(mask))
			return -EINVAL;
		if (dir)
			*dir = 0;
		return snd_mask_value(mask);
	}
	if (hw_is_interval(var))
	{
		const struct snd_interval *i = hw_param_interval_c(params, var);
		if (!snd_interval_single(i))
			return -EINVAL;
		if (dir)
			*dir = i->openmin;
		return snd_interval_value(i);
	}
	return -EINVAL;
}
Example #2
0
static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params,
				 struct snd_soc_dai *dai)
{
	struct davinci_mcbsp_dev *dev = dai->private_data;
	struct davinci_pcm_dma_params *dma_params =
					&dev->dma_params[substream->stream];
	struct snd_interval *i = NULL;
	int mcbsp_word_length;
	unsigned int rcr, xcr, srgr;
	u32 spcr;
	snd_pcm_format_t fmt;
	unsigned element_cnt = 1;

	/* general line settings */
	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
	} else {
		spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
	}

	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
	srgr = DAVINCI_MCBSP_SRGR_FSGM;
	srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);

	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
	srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);

	rcr = DAVINCI_MCBSP_RCR_RFIG;
	xcr = DAVINCI_MCBSP_XCR_XFIG;
	if (dev->mode == MOD_DSP_B) {
		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);
		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);
	} else {
		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
	}
	/* Determine xfer data type */
	fmt = params_format(params);
	if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) {
		printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n");
		return -EINVAL;
	}

	if (params_channels(params) == 2) {
		element_cnt = 2;
		if (double_fmt[fmt] && dev->enable_channel_combine) {
			element_cnt = 1;
			fmt = double_fmt[fmt];
		}
	}
	dma_params->acnt = dma_params->data_type = data_type[fmt];
	dma_params->fifo_level = 0;
	mcbsp_word_length = asp_word_length[fmt];
	rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
	xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);

	rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
		DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
	xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
		DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
	else
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
	return 0;
}
Example #3
0
static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params,
				 struct snd_soc_dai *dai)
{
	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
	struct snd_interval *i = NULL;
	int mcbsp_word_length, master;
	unsigned int rcr, xcr, srgr, clk_div, freq, framesize;
	u32 spcr;
	snd_pcm_format_t fmt;
	unsigned element_cnt = 1;

	/* general line settings */
	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
	} else {
		spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
	}

	master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK;
	fmt = params_format(params);
	mcbsp_word_length = asp_word_length[fmt];

	switch (master) {
	case SND_SOC_DAIFMT_CBS_CFS:
		freq = clk_get_rate(dev->clk);
		srgr = DAVINCI_MCBSP_SRGR_FSGM |
		       DAVINCI_MCBSP_SRGR_CLKSM;
		srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length *
						8 - 1);
		if (dev->i2s_accurate_sck) {
			clk_div = 256;
			do {
				framesize = (freq / (--clk_div)) /
				params->rate_num *
					params->rate_den;
			} while (((framesize < 33) || (framesize > 4095)) &&
				 (clk_div));
			clk_div--;
			srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1);
		} else {
			/* symmetric waveforms */
			clk_div = freq / (mcbsp_word_length * 16) /
				  params->rate_num * params->rate_den;
			srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *
							16 - 1);
		}
		clk_div &= 0xFF;
		srgr |= clk_div;
		break;
	case SND_SOC_DAIFMT_CBM_CFS:
		srgr = DAVINCI_MCBSP_SRGR_FSGM;
		clk_div = dev->clk_div - 1;
		srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1);
		srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1);
		clk_div &= 0xFF;
		srgr |= clk_div;
		break;
	case SND_SOC_DAIFMT_CBM_CFM:
		/* Clock and frame sync given from external sources */
		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
		srgr = DAVINCI_MCBSP_SRGR_FSGM;
		srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
		pr_debug("%s - %d  FWID set: re-read srgr = %X\n",
			__func__, __LINE__, snd_interval_value(i) - 1);

		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
		srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
		break;
	default:
		return -EINVAL;
	}
	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);

	rcr = DAVINCI_MCBSP_RCR_RFIG;
	xcr = DAVINCI_MCBSP_XCR_XFIG;
	if (dev->mode == MOD_DSP_B) {
		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);
		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);
	} else {
		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
	}
	/* Determine xfer data type */
	fmt = params_format(params);
	if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) {
		printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n");
		return -EINVAL;
	}

	if (params_channels(params) == 2) {
		element_cnt = 2;
		if (double_fmt[fmt] && dev->enable_channel_combine) {
			element_cnt = 1;
			fmt = double_fmt[fmt];
		}
		switch (master) {
		case SND_SOC_DAIFMT_CBS_CFS:
		case SND_SOC_DAIFMT_CBS_CFM:
			rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0);
			xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0);
			rcr |= DAVINCI_MCBSP_RCR_RPHASE;
			xcr |= DAVINCI_MCBSP_XCR_XPHASE;
			break;
		case SND_SOC_DAIFMT_CBM_CFM:
		case SND_SOC_DAIFMT_CBM_CFS:
			rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1);
			xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1);
			break;
		default:
			return -EINVAL;
		}
	}
	mcbsp_word_length = asp_word_length[fmt];

	switch (master) {
	case SND_SOC_DAIFMT_CBS_CFS:
	case SND_SOC_DAIFMT_CBS_CFM:
		rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0);
		xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0);
		break;
	case SND_SOC_DAIFMT_CBM_CFM:
	case SND_SOC_DAIFMT_CBM_CFS:
		rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
		xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
		break;
	default:
		return -EINVAL;
	}

	rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
		DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
	xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
		DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
	else
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);

	pr_debug("%s - %d  srgr=%X\n", __func__, __LINE__, srgr);
	pr_debug("%s - %d  xcr=%X\n", __func__, __LINE__, xcr);
	pr_debug("%s - %d  rcr=%X\n", __func__, __LINE__, rcr);
	return 0;
}
Example #4
0
static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params,
				 struct snd_soc_dai *dai)
{
	struct davinci_mcbsp_dev *dev = dai->private_data;
	struct davinci_pcm_dma_params *dma_params =
					&dev->dma_params[substream->stream];
	struct snd_interval *i = NULL;
	int mcbsp_word_length;
	unsigned int rcr, xcr, srgr;
	u32 spcr;

	/* general line settings */
	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
		spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
	} else {
		spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
	}

	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
	srgr = DAVINCI_MCBSP_SRGR_FSGM;
	srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);

	i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
	srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);

	rcr = DAVINCI_MCBSP_RCR_RFIG;
	xcr = DAVINCI_MCBSP_XCR_XFIG;
	if (dev->mode == MOD_DSP_B) {
		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);
		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);
	} else {
		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
	}
	/* Determine xfer data type */
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S8:
		dma_params->data_type = 1;
		mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
		break;
	case SNDRV_PCM_FORMAT_S16_LE:
		dma_params->data_type = 2;
		mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
		break;
	case SNDRV_PCM_FORMAT_S32_LE:
		dma_params->data_type = 4;
		mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
		break;
	default:
		printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n");
		return -EINVAL;
	}

	dma_params->acnt  = dma_params->data_type;
	rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
	xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);

	rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
		DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
	xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
		DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
	else
		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
	return 0;
}