sound/soc/codecs/es7134.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/es7134.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/es7134.c
Extension
.c
Size
8032 bytes
Lines
317
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 es7134_clock_mode {
	unsigned int rate_min;
	unsigned int rate_max;
	unsigned int *mclk_fs;
	unsigned int mclk_fs_num;
};

struct es7134_chip {
	struct snd_soc_dai_driver *dai_drv;
	const struct es7134_clock_mode *modes;
	unsigned int mode_num;
	const struct snd_soc_dapm_widget *extra_widgets;
	unsigned int extra_widget_num;
	const struct snd_soc_dapm_route *extra_routes;
	unsigned int extra_route_num;
};

struct es7134_data {
	unsigned int mclk;
	const struct es7134_chip *chip;
};

static int es7134_check_mclk(struct snd_soc_dai *dai,
			     struct es7134_data *priv,
			     unsigned int rate)
{
	unsigned int mfs = priv->mclk / rate;
	int i, j;

	for (i = 0; i < priv->chip->mode_num; i++) {
		const struct es7134_clock_mode *mode = &priv->chip->modes[i];

		if (rate < mode->rate_min || rate > mode->rate_max)
			continue;

		for (j = 0; j < mode->mclk_fs_num; j++) {
			if (mode->mclk_fs[j] == mfs)
				return 0;
		}

		dev_err(dai->dev, "unsupported mclk_fs %u for rate %u\n",
			mfs, rate);
		return -EINVAL;
	}

	/* should not happen */
	dev_err(dai->dev, "unsupported rate: %u\n", rate);
	return -EINVAL;
}

static int es7134_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *params,
			    struct snd_soc_dai *dai)
{
	struct es7134_data *priv = snd_soc_dai_get_drvdata(dai);

	/* mclk has not been provided, assume it is OK */
	if (!priv->mclk)
		return 0;

	return es7134_check_mclk(dai, priv, params_rate(params));
}

static int es7134_set_sysclk(struct snd_soc_dai *dai, int clk_id,
			     unsigned int freq, int dir)
{
	struct es7134_data *priv = snd_soc_dai_get_drvdata(dai);

	if (dir == SND_SOC_CLOCK_IN && clk_id == 0) {
		priv->mclk = freq;
		return 0;
	}

	return -ENOTSUPP;
}

static int es7134_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
	fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK |
		SND_SOC_DAIFMT_MASTER_MASK);

	if (fmt != (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
		    SND_SOC_DAIFMT_CBC_CFC)) {
		dev_err(codec_dai->dev, "Invalid DAI format\n");
		return -EINVAL;
	}

	return 0;
}

Annotation

Implementation Notes