summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown2009-04-22 19:24:55 +0200
committerMark Brown2009-04-22 20:10:13 +0200
commit246d0a17f5e09af0794960164269fc8988a8811c (patch)
tree3c10da44183691038959ba0b53d5598ac1aaabc4 /sound/soc/soc-dapm.c
parentASoC: OMAP: Add checking to detect bufferless pcms (diff)
downloadkernel-qcow2-linux-246d0a17f5e09af0794960164269fc8988a8811c.tar.gz
kernel-qcow2-linux-246d0a17f5e09af0794960164269fc8988a8811c.tar.xz
kernel-qcow2-linux-246d0a17f5e09af0794960164269fc8988a8811c.zip
ASoC: Add power supply widget to DAPM
Many modern CODECs have shared resources on chip which must be enabled for portions of the chip to work but which can be disabled at other times in order to achieve power savings. Examples of such resources include power supplies and some internal clocks. Since these widgets are dependencies for the audio path but do not carry audio signals they require slightly different handling to most widgets - they do not contribute to the audio path and so should not be counted as either inputs or outputs during path walks. Cases where one supply provides a supply for another will require additional work. There is also room for more optimisation of the graph walking to avoid repeated checks for the same thing. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d3d17354e76c..7847f80e96d1 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -52,17 +52,19 @@
/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
- snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
- snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac,
- snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga,
- snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
+ snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias,
+ snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
+ snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl,
+ snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
+ snd_soc_dapm_post
};
static int dapm_down_seq[] = {
snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
- snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post
+ snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply,
+ snd_soc_dapm_post
};
static int dapm_status = 1;
@@ -165,6 +167,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_dac:
case snd_soc_dapm_micbias:
case snd_soc_dapm_vmid:
+ case snd_soc_dapm_supply:
p->connect = 1;
break;
/* does effect routing - dynamically connected */
@@ -435,6 +438,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
struct snd_soc_dapm_path *path;
int con = 0;
+ if (widget->id == snd_soc_dapm_supply)
+ return 0;
+
if (widget->id == snd_soc_dapm_adc && widget->active)
return 1;
@@ -471,6 +477,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
struct snd_soc_dapm_path *path;
int con = 0;
+ if (widget->id == snd_soc_dapm_supply)
+ return 0;
+
/* active stream ? */
if (widget->id == snd_soc_dapm_dac && widget->active)
return 1;
@@ -622,6 +631,26 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
}
}
+/* Check to see if a power supply is needed */
+static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
+{
+ struct snd_soc_dapm_path *path;
+ int power = 0;
+
+ /* Check if one of our outputs is connected */
+ list_for_each_entry(path, &w->sinks, list_source) {
+ if (path->sink && path->sink->power_check &&
+ path->sink->power_check(path->sink)) {
+ power = 1;
+ break;
+ }
+ }
+
+ dapm_clear_walk(w->codec);
+
+ return power;
+}
+
/*
* Scan a single DAPM widget for a complete audio path and update the
* power status appropriately.
@@ -752,6 +781,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
case snd_soc_dapm_pga:
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
+ case snd_soc_dapm_supply:
if (w->name) {
in = is_connected_input_ep(w);
dapm_clear_walk(w->codec);
@@ -880,6 +910,7 @@ static ssize_t dapm_widget_show(struct device *dev,
case snd_soc_dapm_pga:
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
+ case snd_soc_dapm_supply:
if (w->name)
count += sprintf(buf + count, "%s: %s\n",
w->name, w->power ? "On":"Off");
@@ -1044,6 +1075,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
case snd_soc_dapm_vmid:
case snd_soc_dapm_pre:
case snd_soc_dapm_post:
+ case snd_soc_dapm_supply:
list_add(&path->list, &codec->dapm_paths);
list_add(&path->list_sink, &wsink->sources);
list_add(&path->list_source, &wsource->sinks);
@@ -1164,6 +1196,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
case snd_soc_dapm_line:
w->power_check = dapm_generic_check_power;
break;
+ case snd_soc_dapm_supply:
+ w->power_check = dapm_supply_check_power;
case snd_soc_dapm_vmid:
case snd_soc_dapm_pre:
case snd_soc_dapm_post: