1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2020 Bootlin SA
4 * Author: Alexandre Belloni <alexandre.belloni@bootlin.com>
7 #include <linux/gpio/consumer.h>
8 #include <linux/module.h>
9 #include <linux/regulator/consumer.h>
10 #include <sound/soc.h>
13 struct gpio_desc
*gpiod_mux
;
17 static const char * const simple_mux_texts
[] = {
21 static SOC_ENUM_SINGLE_EXT_DECL(simple_mux_enum
, simple_mux_texts
);
23 static int simple_mux_control_get(struct snd_kcontrol
*kcontrol
,
24 struct snd_ctl_elem_value
*ucontrol
)
26 struct snd_soc_dapm_context
*dapm
= snd_soc_dapm_kcontrol_dapm(kcontrol
);
27 struct snd_soc_component
*c
= snd_soc_dapm_to_component(dapm
);
28 struct simple_mux
*priv
= snd_soc_component_get_drvdata(c
);
30 ucontrol
->value
.enumerated
.item
[0] = priv
->mux
;
35 static int simple_mux_control_put(struct snd_kcontrol
*kcontrol
,
36 struct snd_ctl_elem_value
*ucontrol
)
38 struct snd_soc_dapm_context
*dapm
= snd_soc_dapm_kcontrol_dapm(kcontrol
);
39 struct soc_enum
*e
= (struct soc_enum
*)kcontrol
->private_value
;
40 struct snd_soc_component
*c
= snd_soc_dapm_to_component(dapm
);
41 struct simple_mux
*priv
= snd_soc_component_get_drvdata(c
);
43 if (ucontrol
->value
.enumerated
.item
[0] > e
->items
)
46 if (priv
->mux
== ucontrol
->value
.enumerated
.item
[0])
49 priv
->mux
= ucontrol
->value
.enumerated
.item
[0];
51 gpiod_set_value_cansleep(priv
->gpiod_mux
, priv
->mux
);
53 return snd_soc_dapm_mux_update_power(dapm
, kcontrol
,
54 ucontrol
->value
.enumerated
.item
[0],
58 static const struct snd_kcontrol_new simple_mux_mux
=
59 SOC_DAPM_ENUM_EXT("Muxer", simple_mux_enum
, simple_mux_control_get
, simple_mux_control_put
);
61 static const struct snd_soc_dapm_widget simple_mux_dapm_widgets
[] = {
62 SND_SOC_DAPM_INPUT("IN1"),
63 SND_SOC_DAPM_INPUT("IN2"),
64 SND_SOC_DAPM_MUX("MUX", SND_SOC_NOPM
, 0, 0, &simple_mux_mux
),
65 SND_SOC_DAPM_OUTPUT("OUT"),
68 static const struct snd_soc_dapm_route simple_mux_dapm_routes
[] = {
69 { "OUT", NULL
, "MUX" },
70 { "MUX", "Input 1", "IN1" },
71 { "MUX", "Input 2", "IN2" },
74 static const struct snd_soc_component_driver simple_mux_component_driver
= {
75 .dapm_widgets
= simple_mux_dapm_widgets
,
76 .num_dapm_widgets
= ARRAY_SIZE(simple_mux_dapm_widgets
),
77 .dapm_routes
= simple_mux_dapm_routes
,
78 .num_dapm_routes
= ARRAY_SIZE(simple_mux_dapm_routes
),
81 static int simple_mux_probe(struct platform_device
*pdev
)
83 struct device
*dev
= &pdev
->dev
;
84 struct simple_mux
*priv
;
87 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
91 dev_set_drvdata(dev
, priv
);
93 priv
->gpiod_mux
= devm_gpiod_get(dev
, "mux", GPIOD_OUT_LOW
);
94 if (IS_ERR(priv
->gpiod_mux
)) {
95 err
= PTR_ERR(priv
->gpiod_mux
);
96 if (err
!= -EPROBE_DEFER
)
97 dev_err(dev
, "Failed to get 'mux' gpio: %d", err
);
101 return devm_snd_soc_register_component(dev
, &simple_mux_component_driver
, NULL
, 0);
105 static const struct of_device_id simple_mux_ids
[] = {
106 { .compatible
= "simple-audio-mux", },
109 MODULE_DEVICE_TABLE(of
, simple_mux_ids
);
112 static struct platform_driver simple_mux_driver
= {
114 .name
= "simple-mux",
115 .of_match_table
= of_match_ptr(simple_mux_ids
),
117 .probe
= simple_mux_probe
,
120 module_platform_driver(simple_mux_driver
);
122 MODULE_DESCRIPTION("ASoC Simple Audio Mux driver");
123 MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
124 MODULE_LICENSE("GPL");