sound/soc/codecs/dmic.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/dmic.c
Extension
.c
Size
5273 bytes
Lines
217
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 dmic {
	struct gpio_desc *gpio_en;
	struct regulator *vref;
	int wakeup_delay;
	/* Delay after DMIC mode switch */
	int modeswitch_delay;
};

static int dmic_daiops_trigger(struct snd_pcm_substream *substream,
			       int cmd, struct snd_soc_dai *dai)
{
	struct snd_soc_component *component = dai->component;
	struct dmic *dmic = snd_soc_component_get_drvdata(component);

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_STOP:
		if (dmic->modeswitch_delay)
			mdelay(dmic->modeswitch_delay);

		break;
	}

	return 0;
}

static const struct snd_soc_dai_ops dmic_dai_ops = {
	.trigger	= dmic_daiops_trigger,
};

static int dmic_aif_event(struct snd_soc_dapm_widget *w,
			  struct snd_kcontrol *kcontrol, int event) {
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	struct dmic *dmic = snd_soc_component_get_drvdata(component);
	int ret = 0;

	switch (event) {
	case SND_SOC_DAPM_POST_PMU:
		if (dmic->gpio_en)
			gpiod_set_value_cansleep(dmic->gpio_en, 1);

		if (dmic->vref) {
			ret = regulator_enable(dmic->vref);
			if (ret)
				return ret;
		}

		if (dmic->wakeup_delay)
			msleep(dmic->wakeup_delay);
		break;
	case SND_SOC_DAPM_POST_PMD:
		if (dmic->gpio_en)
			gpiod_set_value_cansleep(dmic->gpio_en, 0);

		if (dmic->vref)
			ret = regulator_disable(dmic->vref);

		break;
	}

	return ret;
}

static struct snd_soc_dai_driver dmic_dai = {
	.name = "dmic-hifi",
	.capture = {
		.stream_name = "Capture",
		.channels_min = 1,
		.channels_max = 8,
		.rates = SNDRV_PCM_RATE_CONTINUOUS,
		.formats = SNDRV_PCM_FMTBIT_S32_LE
			| SNDRV_PCM_FMTBIT_S24_LE
			| SNDRV_PCM_FMTBIT_S16_LE
			| SNDRV_PCM_FMTBIT_DSD_U8
			| SNDRV_PCM_FMTBIT_DSD_U16_LE
			| SNDRV_PCM_FMTBIT_DSD_U32_LE
			| SNDRV_PCM_FMTBIT_DSD_U16_BE
			| SNDRV_PCM_FMTBIT_DSD_U32_BE,
	},
	.ops    = &dmic_dai_ops,
};

static int dmic_component_probe(struct snd_soc_component *component)
{
	struct dmic *dmic;

	dmic = devm_kzalloc(component->dev, sizeof(*dmic), GFP_KERNEL);
	if (!dmic)
		return -ENOMEM;

	dmic->vref = devm_regulator_get_optional(component->dev, "vref");

Annotation

Implementation Notes