sound/soc/codecs/simple-mux.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/simple-mux.c
Extension
.c
Size
6073 bytes
Lines
193
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 simple_mux {
	struct gpio_desc *gpiod_mux;
	unsigned int mux;
	const char *mux_texts[MUX_TEXT_SIZE];
	unsigned int idle_state;
	struct soc_enum mux_enum;
	struct snd_kcontrol_new mux_mux;
	struct snd_soc_dapm_widget mux_widgets[MUX_WIDGET_SIZE];
	struct snd_soc_dapm_route mux_routes[MUX_ROUTE_SIZE];
	struct snd_soc_component_driver mux_driver;
};

static const char * const simple_mux_texts[MUX_TEXT_SIZE] = {
	"Input 1", "Input 2"
};

static SOC_ENUM_SINGLE_EXT_DECL(simple_mux_enum, simple_mux_texts);

static int simple_mux_control_get(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
	struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
	struct simple_mux *priv = snd_soc_component_get_drvdata(c);

	ucontrol->value.enumerated.item[0] = priv->mux;

	return 0;
}

static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
	struct simple_mux *priv = snd_soc_component_get_drvdata(c);

	if (ucontrol->value.enumerated.item[0] >= e->items)
		return -EINVAL;

	if (priv->mux == ucontrol->value.enumerated.item[0])
		return 0;

	priv->mux = ucontrol->value.enumerated.item[0];

	if (priv->idle_state != MUX_IDLE_AS_IS &&
	    snd_soc_dapm_get_bias_level(dapm) < SND_SOC_BIAS_PREPARE)
		return 0;

	gpiod_set_value_cansleep(priv->gpiod_mux, priv->mux);

	return snd_soc_dapm_mux_update_power(dapm, kcontrol,
					     ucontrol->value.enumerated.item[0],
					     e, NULL);
}

static unsigned int simple_mux_read(struct snd_soc_component *component,
				    unsigned int reg)
{
	struct simple_mux *priv = snd_soc_component_get_drvdata(component);

	return priv->mux;
}

static const struct snd_kcontrol_new simple_mux_mux =
	SOC_DAPM_ENUM_EXT("Muxer", simple_mux_enum, simple_mux_control_get, simple_mux_control_put);

static int simple_mux_event(struct snd_soc_dapm_widget *w,
			    struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
	struct simple_mux *priv = snd_soc_component_get_drvdata(c);

	if (priv->idle_state != MUX_IDLE_AS_IS) {
		switch (event) {
		case SND_SOC_DAPM_PRE_PMU:
			gpiod_set_value_cansleep(priv->gpiod_mux, priv->mux);
			break;
		case SND_SOC_DAPM_POST_PMD:
			gpiod_set_value_cansleep(priv->gpiod_mux, priv->idle_state);
			break;
		default:
			break;
		}
	}

	return 0;
}

Annotation

Implementation Notes