6
6
7
7
#include <linux/gpio/consumer.h>
8
8
#include <linux/module.h>
9
+ #include <linux/mux/driver.h>
9
10
#include <linux/regulator/consumer.h>
10
11
#include <sound/soc.h>
11
12
@@ -16,6 +17,7 @@ struct simple_mux {
16
17
struct gpio_desc * gpiod_mux ;
17
18
unsigned int mux ;
18
19
const char * mux_texts [MUX_TEXT_SIZE ];
20
+ unsigned int idle_state ;
19
21
struct soc_enum mux_enum ;
20
22
struct snd_kcontrol_new mux_mux ;
21
23
struct snd_soc_dapm_widget mux_widgets [MUX_WIDGET_SIZE ];
@@ -57,6 +59,9 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
57
59
58
60
priv -> mux = ucontrol -> value .enumerated .item [0 ];
59
61
62
+ if (priv -> idle_state != MUX_IDLE_AS_IS && dapm -> bias_level < SND_SOC_BIAS_PREPARE )
63
+ return 0 ;
64
+
60
65
gpiod_set_value_cansleep (priv -> gpiod_mux , priv -> mux );
61
66
62
67
return snd_soc_dapm_mux_update_power (dapm , kcontrol ,
@@ -75,10 +80,33 @@ static unsigned int simple_mux_read(struct snd_soc_component *component,
75
80
static const struct snd_kcontrol_new simple_mux_mux =
76
81
SOC_DAPM_ENUM_EXT ("Muxer" , simple_mux_enum , simple_mux_control_get , simple_mux_control_put );
77
82
83
+ static int simple_mux_event (struct snd_soc_dapm_widget * w ,
84
+ struct snd_kcontrol * kcontrol , int event )
85
+ {
86
+ struct snd_soc_component * c = snd_soc_dapm_to_component (w -> dapm );
87
+ struct simple_mux * priv = snd_soc_component_get_drvdata (c );
88
+
89
+ if (priv -> idle_state != MUX_IDLE_AS_IS ) {
90
+ switch (event ) {
91
+ case SND_SOC_DAPM_PRE_PMU :
92
+ gpiod_set_value_cansleep (priv -> gpiod_mux , priv -> mux );
93
+ break ;
94
+ case SND_SOC_DAPM_POST_PMD :
95
+ gpiod_set_value_cansleep (priv -> gpiod_mux , priv -> idle_state );
96
+ break ;
97
+ default :
98
+ break ;
99
+ }
100
+ }
101
+
102
+ return 0 ;
103
+ }
104
+
78
105
static const struct snd_soc_dapm_widget simple_mux_dapm_widgets [MUX_WIDGET_SIZE ] = {
79
106
SND_SOC_DAPM_INPUT ("IN1" ),
80
107
SND_SOC_DAPM_INPUT ("IN2" ),
81
- SND_SOC_DAPM_MUX ("MUX" , SND_SOC_NOPM , 0 , 0 , & simple_mux_mux ), // see simple_mux_probe()
108
+ SND_SOC_DAPM_MUX_E ("MUX" , SND_SOC_NOPM , 0 , 0 , & simple_mux_mux , // see simple_mux_probe()
109
+ simple_mux_event , SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD ),
82
110
SND_SOC_DAPM_OUTPUT ("OUT" ),
83
111
};
84
112
@@ -93,6 +121,7 @@ static int simple_mux_probe(struct platform_device *pdev)
93
121
struct device * dev = & pdev -> dev ;
94
122
struct device_node * np = dev -> of_node ;
95
123
struct simple_mux * priv ;
124
+ int ret ;
96
125
97
126
priv = devm_kzalloc (dev , sizeof (* priv ), GFP_KERNEL );
98
127
if (!priv )
@@ -121,6 +150,14 @@ static int simple_mux_probe(struct platform_device *pdev)
121
150
/* Overwrite text ("Input 1", "Input 2") if property exists */
122
151
of_property_read_string_array (np , "state-labels" , priv -> mux_texts , MUX_TEXT_SIZE );
123
152
153
+ ret = of_property_read_u32 (np , "idle-state" , & priv -> idle_state );
154
+ if (ret < 0 ) {
155
+ priv -> idle_state = MUX_IDLE_AS_IS ;
156
+ } else if (priv -> idle_state != MUX_IDLE_AS_IS && priv -> idle_state >= 2 ) {
157
+ dev_err (dev , "invalid idle-state %u\n" , priv -> idle_state );
158
+ return - EINVAL ;
159
+ }
160
+
124
161
/* switch to use priv data instead of default */
125
162
priv -> mux_enum .texts = priv -> mux_texts ;
126
163
priv -> mux_mux .private_value = (unsigned long )& priv -> mux_enum ;
0 commit comments