sound/soc/fsl/imx-audmix.c

Source file repositories/reference/linux-study-clean/sound/soc/fsl/imx-audmix.c

File Facts

System
Linux kernel
Corpus path
sound/soc/fsl/imx-audmix.c
Extension
.c
Size
9399 bytes
Lines
340
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct imx_audmix {
	struct platform_device *pdev;
	struct snd_soc_card card;
	struct platform_device *audmix_pdev;
	struct platform_device *out_pdev;
	int num_dai;
	struct snd_soc_dai_link *dai;
	int num_dai_conf;
	struct snd_soc_codec_conf *dai_conf;
	int num_dapm_routes;
	struct snd_soc_dapm_route *dapm_routes;
};

static int imx_audmix_fe_startup(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	int ret;

	ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
					   1, 8);
	if (ret < 0)
		return ret;

	return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
					    FSL_AUDMIX_FORMATS);
}

static int imx_audmix_fe_hw_params(struct snd_pcm_substream *substream,
				   struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
	struct device *dev = rtd->card->dev;
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
	unsigned int fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF;
	u32 channels = params_channels(params);
	int ret, dir;

	/* For playback the AUDMIX is consumer, and for record is provider */
	fmt |= tx ? SND_SOC_DAIFMT_BP_FP : SND_SOC_DAIFMT_BC_FC;
	dir  = tx ? SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN;

	/* set DAI configuration */
	ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0), fmt);
	if (ret) {
		dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
		return ret;
	}

	ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0), FSL_SAI_CLK_MAST1, 0, dir);
	if (ret) {
		dev_err(dev, "failed to set cpu sysclk: %d\n", ret);
		return ret;
	}

	/*
	 * Per datasheet, AUDMIX expects 8 slots and 32 bits
	 * for every slot in TDM mode.
	 */
	ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_cpu(rtd, 0), BIT(channels) - 1,
				       BIT(channels) - 1, 8, 32);
	if (ret)
		dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);

	return ret;
}

static int imx_audmix_be_hw_params(struct snd_pcm_substream *substream,
				   struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
	struct device *dev = rtd->card->dev;
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
	unsigned int fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF;
	int ret;

	if (!tx)
		return 0;

	/* For playback the AUDMIX is consumer */
	fmt |= SND_SOC_DAIFMT_BC_FC;

	/* set AUDMIX DAI configuration */
	ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0), fmt);
	if (ret)
		dev_err(dev, "failed to set AUDMIX DAI fmt: %d\n", ret);

	return ret;
}

static const struct snd_soc_ops imx_audmix_fe_ops = {

Annotation

Implementation Notes