sound/soc/codecs/es7241.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/es7241.c
Extension
.c
Size
7501 bytes
Lines
312
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 es7241_clock_mode {
	unsigned int rate_min;
	unsigned int rate_max;
	unsigned int *slv_mfs;
	unsigned int slv_mfs_num;
	unsigned int mst_mfs;
	unsigned int mst_m0:1;
	unsigned int mst_m1:1;
};

struct es7241_chip {
	const struct es7241_clock_mode *modes;
	unsigned int mode_num;
};

struct es7241_data {
	struct gpio_desc *reset;
	struct gpio_desc *m0;
	struct gpio_desc *m1;
	unsigned int fmt;
	unsigned int mclk;
	bool is_consumer;
	const struct es7241_chip *chip;
};

static void es7241_set_mode(struct es7241_data *priv,  int m0, int m1)
{
	/* put the device in reset */
	gpiod_set_value_cansleep(priv->reset, 0);

	/* set the mode */
	gpiod_set_value_cansleep(priv->m0, m0);
	gpiod_set_value_cansleep(priv->m1, m1);

	/* take the device out of reset - datasheet does not specify a delay */
	gpiod_set_value_cansleep(priv->reset, 1);
}

static int es7241_set_consumer_mode(struct es7241_data *priv,
				    const struct es7241_clock_mode *mode,
				    unsigned int mfs)
{
	int j;

	if (!mfs)
		goto out_ok;

	for (j = 0; j < mode->slv_mfs_num; j++) {
		if (mode->slv_mfs[j] == mfs)
			goto out_ok;
	}

	return -EINVAL;

out_ok:
	es7241_set_mode(priv, 1, 1);
	return 0;
}

static int es7241_set_provider_mode(struct es7241_data *priv,
				    const struct es7241_clock_mode *mode,
				    unsigned int mfs)
{
	/*
	 * We can't really set clock ratio, if the mclk/lrclk is different
	 * from what we provide, then error out
	 */
	if (mfs && mfs != mode->mst_mfs)
		return -EINVAL;

	es7241_set_mode(priv, mode->mst_m0, mode->mst_m1);

	return 0;
}

static int es7241_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *params,
			    struct snd_soc_dai *dai)
{
	struct es7241_data *priv = snd_soc_dai_get_drvdata(dai);
	unsigned int rate = params_rate(params);
	unsigned int mfs = priv->mclk / rate;
	int i;

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

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

Annotation

Implementation Notes