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; }
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; }
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; }