/** * qcom_snd_sdw_startup() - Helper to start Soundwire stream for SoC audio card * @substream: The PCM substream from audio, as passed to snd_soc_ops->startup() * * Helper for the SoC audio card (snd_soc_ops->startup()) to allocate and set * Soundwire stream runtime to each codec DAI. * * The shutdown() callback should call sdw_release_stream() on the same * sdw_stream_runtime. * * Return: 0 or errno
*/ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream)
{ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
u32 rx_ch[SDW_MAX_PORTS], tx_ch[SDW_MAX_PORTS]; struct sdw_stream_runtime *sruntime; struct snd_soc_dai *codec_dai;
u32 rx_ch_cnt = 0, tx_ch_cnt = 0; int ret, i, j;
sruntime = sdw_alloc_stream(cpu_dai->name, SDW_STREAM_PCM); if (!sruntime) return -ENOMEM;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_stream(codec_dai, sruntime,
substream->stream); if (ret < 0 && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to set sdw stream on %s\n", codec_dai->name); goto err_set_stream;
} elseif (ret == -ENOTSUPP) { /* Ignore unsupported */ continue;
}
ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch,
&rx_ch_cnt, rx_ch); if (ret != 0 && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to get codec chan map %s\n", codec_dai->name); goto err_set_stream;
} elseif (ret == -ENOTSUPP) { /* Ignore unsupported */ continue;
}
}
switch (cpu_dai->id) { case RX_CODEC_DMA_RX_0: case TX_CODEC_DMA_TX_3: if (tx_ch_cnt || rx_ch_cnt) {
for_each_rtd_codec_dais(rtd, j, codec_dai) {
ret = snd_soc_dai_set_channel_map(codec_dai,
tx_ch_cnt, tx_ch,
rx_ch_cnt, rx_ch); if (ret != 0 && ret != -ENOTSUPP) goto err_set_stream;
}
}
}
switch (cpu_dai->id) { case WSA_CODEC_DMA_RX_0: case WSA_CODEC_DMA_RX_1: case RX_CODEC_DMA_RX_0: case RX_CODEC_DMA_RX_1: case TX_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3: break; default: return 0;
}
if (*stream_prepared) return 0;
ret = sdw_prepare_stream(sruntime); if (ret) return ret;
/** * NOTE: there is a strict hw requirement about the ordering of port * enables and actual WSA881x PA enable. PA enable should only happen * after soundwire ports are enabled if not DC on the line is * accumulated resulting in Click/Pop Noise * PA enable/mute are handled as part of codec DAPM and digital mute.
*/
ret = sdw_enable_stream(sruntime); if (ret) {
sdw_deprepare_stream(sruntime); return ret;
}
*stream_prepared = true;
switch (cpu_dai->id) { case WSA_CODEC_DMA_RX_0: case RX_CODEC_DMA_RX_0: case RX_CODEC_DMA_RX_1: case TX_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3:
for_each_rtd_codec_dais(rtd, i, codec_dai) {
sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); if (sruntime != ERR_PTR(-ENOTSUPP))
*psruntime = sruntime;
} break;
}
switch (cpu_dai->id) { case WSA_CODEC_DMA_RX_0: case WSA_CODEC_DMA_RX_1: case RX_CODEC_DMA_RX_0: case RX_CODEC_DMA_RX_1: case TX_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_1: case TX_CODEC_DMA_TX_2: case TX_CODEC_DMA_TX_3: if (sruntime && *stream_prepared) {
sdw_disable_stream(sruntime);
sdw_deprepare_stream(sruntime);
*stream_prepared = false;
} break; default: break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.