示例#1
0
int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
				struct snd_pcm_plugin_format *src_format,
				struct snd_pcm_plugin_format *dst_format,
				struct snd_pcm_plugin **r_plugin)
{
	int err;
	struct linear_priv *data;
	struct snd_pcm_plugin *plugin;

	snd_assert(r_plugin != NULL, return -ENXIO);
	*r_plugin = NULL;

	snd_assert(src_format->rate == dst_format->rate, return -ENXIO);
	snd_assert(src_format->channels == dst_format->channels, return -ENXIO);
	snd_assert(snd_pcm_format_linear(src_format->format) &&
		   snd_pcm_format_linear(dst_format->format), return -ENXIO);

	err = snd_pcm_plugin_build(plug, "linear format conversion",
				   src_format, dst_format,
				   sizeof(struct linear_priv), &plugin);
	if (err < 0)
		return err;
	data = (struct linear_priv *)plugin->extra_data;
	init_data(data, src_format->format, dst_format->format);
	plugin->transfer = linear_transfer;
	*r_plugin = plugin;
	return 0;
}
示例#2
0
int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
				struct snd_pcm_plugin_format *src_format,
				struct snd_pcm_plugin_format *dst_format,
				struct snd_pcm_plugin **r_plugin)
{
	int err;
	struct linear_priv *data;
	struct snd_pcm_plugin *plugin;

	if (snd_BUG_ON(!r_plugin))
		return -ENXIO;
	*r_plugin = NULL;

	if (snd_BUG_ON(src_format->rate != dst_format->rate))
		return -ENXIO;
	if (snd_BUG_ON(src_format->channels != dst_format->channels))
		return -ENXIO;
	if (snd_BUG_ON(!snd_pcm_format_linear(src_format->format) ||
		       !snd_pcm_format_linear(dst_format->format)))
		return -ENXIO;

	err = snd_pcm_plugin_build(plug, "linear format conversion",
				   src_format, dst_format,
				   sizeof(struct linear_priv), &plugin);
	if (err < 0)
		return err;
	data = (struct linear_priv *)plugin->extra_data;
	init_data(data, src_format->format, dst_format->format);
	plugin->transfer = linear_transfer;
	*r_plugin = plugin;
	return 0;
}
示例#3
0
static int snd_pcm_lfloat_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
	snd_pcm_lfloat_t *lfloat = pcm->private_data;
	int err;
	snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_SHM };
	snd_pcm_format_mask_t lformat_mask = { SND_PCM_FMTBIT_LINEAR };
	snd_pcm_format_mask_t fformat_mask = { SND_PCM_FMTBIT_FLOAT };
	err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
					 &access_mask);
	if (err < 0)
		return err;
	err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_FORMAT,
					 snd_pcm_format_linear(lfloat->sformat) ?
					 &fformat_mask : &lformat_mask);
	if (err < 0)
		return err;
	err = _snd_pcm_hw_params_set_subformat(params, SND_PCM_SUBFORMAT_STD);
	if (err < 0)
		return err;
	params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
	return 0;
}
// returns 1 if successful
// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
                            int* sampleSizeInBytes, int* significantBits,
                            int* isSigned, int* isBigEndian, int* enc) {

    *sampleSizeInBytes = (snd_pcm_format_physical_width(alsaFormat) + 7) / 8;
    *significantBits = snd_pcm_format_width(alsaFormat);

    // defaults
    *enc = 0; // PCM
    *isSigned = (snd_pcm_format_signed(alsaFormat) > 0);
    *isBigEndian = (snd_pcm_format_big_endian(alsaFormat) > 0);

    // non-PCM formats
    if (alsaFormat == SND_PCM_FORMAT_MU_LAW) { // Mu-Law
        *sampleSizeInBytes = 8; *enc = 1; *significantBits = *sampleSizeInBytes;
    }
    else if (alsaFormat == SND_PCM_FORMAT_A_LAW) {     // A-Law
        *sampleSizeInBytes = 8; *enc = 2; *significantBits = *sampleSizeInBytes;
    }
    else if (snd_pcm_format_linear(alsaFormat) < 1) {
        return 0;
    }
    return (*sampleSizeInBytes > 0);
}
static int spdif_hw_params(struct snd_pcm_substream *
		substream, struct snd_pcm_hw_params *params,
		struct snd_soc_dai *dai)
{
	struct rockchip_spdif_info *spdif = to_info(dai);
	void __iomem *regs = spdif->regs;
	unsigned long flags;
	int cfgr, dmac, intcr, chnsr_byte[5] = {0};
	int data_type, err_flag, data_len, data_info;
	int bs_num, repetition, burst_info;

	RK_SPDIF_DBG("Entered %s\n", __func__);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		dai->playback_dma_data = &spdif->dma_playback;
	} else {
		pr_err("spdif:Capture is not supported\n");
		return -EINVAL;
	}

	spin_lock_irqsave(&spdif->lock, flags);

	cfgr = readl(regs + CFGR) & CFGR_VALID_DATA_MASK;

	cfgr &= ~CFGR_VALID_DATA_MASK;
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		cfgr |= CFGR_VALID_DATA_16bit;
		break;
	case SNDRV_PCM_FORMAT_S20_3LE:
		cfgr |= CFGR_VALID_DATA_20bit;
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		cfgr |= CFGR_VALID_DATA_24bit;
		break;
	default:
		goto err;
	}

	cfgr &= ~CFGR_HALFWORD_TX_MASK;
	cfgr |= CFGR_HALFWORD_TX_ENABLE;

	/* set most MCLK:192kHz */
	cfgr &= ~CFGR_CLK_RATE_MASK;
	cfgr |= (1<<16);

	cfgr &= ~CFGR_JUSTIFIED_MASK;
	cfgr |= CFGR_JUSTIFIED_RIGHT;

	cfgr &= ~CFGR_CSE_MASK;
	cfgr |= CFGR_CSE_DISABLE;

	cfgr &= ~CFGR_LINEAR_MASK;
	cfgr |= CFGR_LINEAR_PCM;

	/* stream type*/
	if (!snd_pcm_format_linear(params_format(params)))
		cfgr |= CFGR_NON_LINEAR_PCM;

	cfgr &= ~CFGR_PRE_CHANGE_MASK;
	cfgr |= CFGR_PRE_CHANGE_ENALBLE;

	writel(cfgr, regs + CFGR);

	intcr = readl(regs + INTCR) & INTCR_SDBEIE_MASK;
	intcr |= INTCR_SDBEIE_ENABLE;
	writel(intcr, regs + INTCR);

	dmac = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK &
		(~DMACR_TRAN_DATA_LEVEL_MASK);
	dmac |= 0x10;
	writel(dmac, regs + DMACR);

	/*
	* channel byte 0:
	* Bit 1
	* 1 Main data field represents linear PCM samples.
	* 0 Main data field used for purposes other purposes.
	*/
	chnsr_byte[0] = (0x0) | (0x0 << 1) |
		(0x0 << 2) | (0x0 << 3) |
		(0x00 << 6);
	chnsr_byte[1] = (0x0);
	chnsr_byte[2] = (0x0) | (0x0 << 4) | (0x0 << 6);
	chnsr_byte[3] = (0x00) | (0x00);
	chnsr_byte[4] = (0x0 << 4) | (0x01 << 1 | 0x0);

	/* set stream type */
	if (!snd_pcm_format_linear(params_format(params))) {
		chnsr_byte[0] |= (0x1<<1);
		chnsr_byte[4] = (0x0<<4)|(0x00<<1|0x0);
	}
	writel((chnsr_byte[4] << 16)
			| (chnsr_byte[4]),
			regs + SPDIF_CHNSR02_ADDR);
	writel((chnsr_byte[3] << 24) | (chnsr_byte[2] << 16) |
		(chnsr_byte[3] << 8) | (chnsr_byte[2]),
		regs + SPDIF_CHNSR01_ADDR);
	writel((chnsr_byte[1] << 24) | (chnsr_byte[0] << 16) |
		(chnsr_byte[1] << 8) | (chnsr_byte[0]),
		regs + SPDIF_CHNSR00_ADDR);

	/* set non-linear params */
	if (!snd_pcm_format_linear(params_format(params))) {
		switch (params_format(params)) {
		case SNDRV_NON_LINEAR_PCM_FORMAT_AC3:
			/* bit0:6 AC-3:0x01, DTS-I -II -III:11,12,13 */
			data_type = burst_info_DATA_TYPE_AC3;
			/*
			* repetition:AC-3:1536
			* DTS-I -II -III:512,1024,2048 EAC3:6144
			*/
			repetition = 1536;
			break;
		case SNDRV_NON_LINEAR_PCM_FORMAT_DTS_I:
			data_type = BURST_INFO_DATA_TYPE_DTS_I;
			repetition = 512;
			break;
		case SNDRV_NON_LINEAR_PCM_FORMAT_EAC3:
			data_type = burst_info_DATA_TYPE_EAC3;
			repetition = 6144;
			break;
		default:
			return -EINVAL;
		}
		err_flag = 0x0;
		data_len = params_period_size(params) * 2 * 16;
		data_info = 0;
		bs_num = 0x0;
		burst_info = (data_len << 16) | (bs_num << 13) |
			(data_info << 8) | (err_flag << 7) | data_type;
		writel(burst_info, regs + SPDIF_BURST_INFO);
		writel(repetition, regs + SPDIF_REPETTION);
	}
	spin_unlock_irqrestore(&spdif->lock, flags);

	return 0;
err:
	spin_unlock_irqrestore(&spdif->lock, flags);
	return -EINVAL;
}