^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright 2005 Wolfson Microelectronics PLC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Author: Liam Girdwood <lrg@slimlogic.co.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // Features:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // o Changes power status of internal codec blocks depending on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // dynamic configuration of codec internal audio paths and active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // DACs/ADCs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) // o Platform power domain - can support external components i.e. amps and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) // mic/headphone insertion events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) // o Automatic Mic Bias support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) // o Jack insertion power event initiation - e.g. hp insertion will enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) // sinks, dacs, etc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) // o Delayed power down of audio subsystem to reduce pops between a quick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) // device reopen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/async.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/pinctrl/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <trace/events/asoc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SND_SOC_DAPM_DIR_REVERSE(x) ((x == SND_SOC_DAPM_DIR_IN) ? \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) SND_SOC_DAPM_DIR_OUT : SND_SOC_DAPM_DIR_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define snd_soc_dapm_for_each_direction(dir) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) for ((dir) = SND_SOC_DAPM_DIR_IN; (dir) <= SND_SOC_DAPM_DIR_OUT; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) (dir)++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) const char *control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int (*connected)(struct snd_soc_dapm_widget *source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct snd_soc_dapm_widget *sink));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct snd_soc_dapm_widget *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const struct snd_soc_dapm_widget *widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct snd_soc_dapm_widget *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) const struct snd_soc_dapm_widget *widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* dapm power sequences - make this per codec in the future */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static int dapm_up_seq[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) [snd_soc_dapm_pre] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) [snd_soc_dapm_regulator_supply] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) [snd_soc_dapm_pinctrl] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) [snd_soc_dapm_clock_supply] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) [snd_soc_dapm_supply] = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) [snd_soc_dapm_micbias] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) [snd_soc_dapm_vmid] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) [snd_soc_dapm_dai_link] = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) [snd_soc_dapm_dai_in] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) [snd_soc_dapm_dai_out] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) [snd_soc_dapm_aif_in] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) [snd_soc_dapm_aif_out] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) [snd_soc_dapm_mic] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) [snd_soc_dapm_siggen] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) [snd_soc_dapm_input] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) [snd_soc_dapm_output] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) [snd_soc_dapm_mux] = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) [snd_soc_dapm_demux] = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) [snd_soc_dapm_dac] = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) [snd_soc_dapm_switch] = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) [snd_soc_dapm_mixer] = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) [snd_soc_dapm_mixer_named_ctl] = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) [snd_soc_dapm_pga] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) [snd_soc_dapm_buffer] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) [snd_soc_dapm_scheduler] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) [snd_soc_dapm_effect] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) [snd_soc_dapm_src] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) [snd_soc_dapm_asrc] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) [snd_soc_dapm_encoder] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) [snd_soc_dapm_decoder] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) [snd_soc_dapm_adc] = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) [snd_soc_dapm_out_drv] = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) [snd_soc_dapm_hp] = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) [snd_soc_dapm_spk] = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) [snd_soc_dapm_line] = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) [snd_soc_dapm_sink] = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) [snd_soc_dapm_kcontrol] = 13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) [snd_soc_dapm_post] = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static int dapm_down_seq[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) [snd_soc_dapm_pre] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) [snd_soc_dapm_kcontrol] = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) [snd_soc_dapm_adc] = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) [snd_soc_dapm_hp] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) [snd_soc_dapm_spk] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) [snd_soc_dapm_line] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) [snd_soc_dapm_out_drv] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) [snd_soc_dapm_sink] = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) [snd_soc_dapm_pga] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) [snd_soc_dapm_buffer] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) [snd_soc_dapm_scheduler] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) [snd_soc_dapm_effect] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) [snd_soc_dapm_src] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) [snd_soc_dapm_asrc] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) [snd_soc_dapm_encoder] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) [snd_soc_dapm_decoder] = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) [snd_soc_dapm_switch] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) [snd_soc_dapm_mixer_named_ctl] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) [snd_soc_dapm_mixer] = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) [snd_soc_dapm_dac] = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) [snd_soc_dapm_mic] = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) [snd_soc_dapm_siggen] = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) [snd_soc_dapm_input] = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) [snd_soc_dapm_output] = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) [snd_soc_dapm_micbias] = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) [snd_soc_dapm_vmid] = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) [snd_soc_dapm_mux] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) [snd_soc_dapm_demux] = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) [snd_soc_dapm_aif_in] = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) [snd_soc_dapm_aif_out] = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) [snd_soc_dapm_dai_in] = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) [snd_soc_dapm_dai_out] = 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) [snd_soc_dapm_dai_link] = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) [snd_soc_dapm_supply] = 13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) [snd_soc_dapm_clock_supply] = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) [snd_soc_dapm_pinctrl] = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) [snd_soc_dapm_regulator_supply] = 14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) [snd_soc_dapm_post] = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static void dapm_assert_locked(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (dapm->card && dapm->card->instantiated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) lockdep_assert_held(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static void pop_wait(u32 pop_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (pop_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) __printf(3, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (!pop_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) va_start(args, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) vsnprintf(buf, PAGE_SIZE, fmt, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) dev_info(dev, "%s", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return !list_empty(&w->dirty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dapm_assert_locked(w->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!dapm_dirty_widget(w)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) w->name, reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Common implementation for dapm_widget_invalidate_input_paths() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * dapm_widget_invalidate_output_paths(). The function is inlined since the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * combined size of the two specialized functions is only marginally larger then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * the size of the generic function and at the same time the fast path of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * specialized functions is significantly smaller than the generic function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static __always_inline void dapm_widget_invalidate_paths(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct snd_soc_dapm_widget *w, enum snd_soc_dapm_direction dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct snd_soc_dapm_widget *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct snd_soc_dapm_path *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) LIST_HEAD(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dapm_assert_locked(w->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (w->endpoints[dir] == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) list_add_tail(&w->work_list, &list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) w->endpoints[dir] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) list_for_each_entry(w, &list, work_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) snd_soc_dapm_widget_for_each_path(w, dir, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (p->is_supply || p->weak || !p->connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) node = p->node[rdir];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (node->endpoints[dir] != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) node->endpoints[dir] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) list_add_tail(&node->work_list, &list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * dapm_widget_invalidate_input_paths() - Invalidate the cached number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * input paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * @w: The widget for which to invalidate the cached number of input paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Resets the cached number of inputs for the specified widget and all widgets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * that can be reached via outcoming paths from the widget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * This function must be called if the number of output paths for a widget might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * have changed. E.g. if the source state of a widget changes or a path is added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * or activated with the widget as the sink.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static void dapm_widget_invalidate_input_paths(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) dapm_widget_invalidate_paths(w, SND_SOC_DAPM_DIR_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * dapm_widget_invalidate_output_paths() - Invalidate the cached number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * output paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * @w: The widget for which to invalidate the cached number of output paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * Resets the cached number of outputs for the specified widget and all widgets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * that can be reached via incoming paths from the widget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * This function must be called if the number of output paths for a widget might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * have changed. E.g. if the sink state of a widget changes or a path is added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * or activated with the widget as the source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static void dapm_widget_invalidate_output_paths(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dapm_widget_invalidate_paths(w, SND_SOC_DAPM_DIR_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * dapm_path_invalidate() - Invalidates the cached number of inputs and outputs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * for the widgets connected to a path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * @p: The path to invalidate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * Resets the cached number of inputs for the sink of the path and the cached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * number of outputs for the source of the path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * This function must be called when a path is added, removed or the connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * state changes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static void dapm_path_invalidate(struct snd_soc_dapm_path *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Weak paths or supply paths do not influence the number of input or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * output paths of their neighbors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (p->weak || p->is_supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * The number of connected endpoints is the sum of the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * connected endpoints of all neighbors. If a node with 0 connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * endpoints is either connected or disconnected that sum won't change,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * so there is no need to re-check the path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (p->source->endpoints[SND_SOC_DAPM_DIR_IN] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dapm_widget_invalidate_input_paths(p->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (p->sink->endpoints[SND_SOC_DAPM_DIR_OUT] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) dapm_widget_invalidate_output_paths(p->source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) void dapm_mark_endpoints_dirty(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) mutex_lock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) for_each_card_widgets(card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (w->is_ep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dapm_mark_dirty(w, "Rechecking endpoints");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (w->is_ep & SND_SOC_DAPM_EP_SINK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dapm_widget_invalidate_output_paths(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (w->is_ep & SND_SOC_DAPM_EP_SOURCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) dapm_widget_invalidate_input_paths(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) EXPORT_SYMBOL_GPL(dapm_mark_endpoints_dirty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /* create a new dapm widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) const struct snd_soc_dapm_widget *_widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) w = kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (!w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * w->name is duplicated in caller, but w->sname isn't.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * Duplicate it here if defined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (_widget->sname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) w->sname = kstrdup_const(_widget->sname, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!w->sname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) kfree(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct dapm_kcontrol_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct snd_soc_dapm_widget *widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct list_head paths;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct snd_soc_dapm_widget_list *wlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct snd_kcontrol *kcontrol, const char *ctrl_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct dapm_kcontrol_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct soc_mixer_control *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct soc_enum *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) data = kzalloc(sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) INIT_LIST_HEAD(&data->paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) switch (widget->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case snd_soc_dapm_switch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) case snd_soc_dapm_mixer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case snd_soc_dapm_mixer_named_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) mc = (struct soc_mixer_control *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (mc->autodisable && snd_soc_volsw_is_stereo(mc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) dev_warn(widget->dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) "ASoC: Unsupported stereo autodisable control '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ctrl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (mc->autodisable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct snd_soc_dapm_widget template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) name = kasprintf(GFP_KERNEL, "%s %s", ctrl_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) "Autodisable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (!name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto err_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) memset(&template, 0, sizeof(template));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) template.reg = mc->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) template.mask = (1 << fls(mc->max)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) template.shift = mc->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (mc->invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) template.off_val = mc->max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) template.off_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) template.on_val = template.off_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) template.id = snd_soc_dapm_kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) template.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) data->value = template.on_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) data->widget =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) snd_soc_dapm_new_control_unlocked(widget->dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) &template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) kfree(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (IS_ERR(data->widget)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) ret = PTR_ERR(data->widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) goto err_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) case snd_soc_dapm_demux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) case snd_soc_dapm_mux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) e = (struct soc_enum *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (e->autodisable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct snd_soc_dapm_widget template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) name = kasprintf(GFP_KERNEL, "%s %s", ctrl_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) "Autodisable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (!name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto err_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) memset(&template, 0, sizeof(template));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) template.reg = e->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) template.mask = e->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) template.shift = e->shift_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) template.off_val = snd_soc_enum_item_to_val(e, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) template.on_val = template.off_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) template.id = snd_soc_dapm_kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) template.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) data->value = template.on_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) data->widget = snd_soc_dapm_new_control_unlocked(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) widget->dapm, &template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) kfree(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (IS_ERR(data->widget)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ret = PTR_ERR(data->widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) goto err_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) snd_soc_dapm_add_path(widget->dapm, data->widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) widget, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) kcontrol->private_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) err_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) list_del(&data->paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) kfree(data->wlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static struct snd_soc_dapm_widget_list *dapm_kcontrol_get_wlist(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) const struct snd_kcontrol *kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return data->wlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static int dapm_kcontrol_add_widget(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct snd_soc_dapm_widget *widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct snd_soc_dapm_widget_list *new_wlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) unsigned int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (data->wlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) n = data->wlist->num_widgets + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) n = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) new_wlist = krealloc(data->wlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct_size(new_wlist, widgets, n),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (!new_wlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) new_wlist->widgets[n - 1] = widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) new_wlist->num_widgets = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) data->wlist = new_wlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static void dapm_kcontrol_add_path(const struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct snd_soc_dapm_path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) list_add_tail(&path->list_kcontrol, &data->paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static bool dapm_kcontrol_is_powered(const struct snd_kcontrol *kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (!data->widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return data->widget->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static struct list_head *dapm_kcontrol_get_path_list(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) const struct snd_kcontrol *kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return &data->paths;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) #define dapm_kcontrol_for_each_path(path, kcontrol) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) list_kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return data->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) EXPORT_SYMBOL_GPL(dapm_kcontrol_get_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static bool dapm_kcontrol_set_value(const struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) unsigned int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct dapm_kcontrol_data *data = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (data->value == value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (data->widget) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) switch (dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) case snd_soc_dapm_switch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case snd_soc_dapm_mixer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) case snd_soc_dapm_mixer_named_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) data->widget->on_val = value & data->widget->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) case snd_soc_dapm_demux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) case snd_soc_dapm_mux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) data->widget->on_val = value >> data->widget->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) data->widget->on_val = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) data->value = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * snd_soc_dapm_kcontrol_widget() - Returns the widget associated to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) * kcontrol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * @kcontrol: The kcontrol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct snd_kcontrol *kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return dapm_kcontrol_get_wlist(kcontrol)->widgets[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * snd_soc_dapm_kcontrol_dapm() - Returns the dapm context associated to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * kcontrol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * @kcontrol: The kcontrol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * Note: This function must only be used on kcontrols that are known to have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * been registered for a CODEC. Otherwise the behaviour is undefined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct snd_kcontrol *kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return dapm_kcontrol_get_wlist(kcontrol)->widgets[0]->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) EXPORT_SYMBOL_GPL(snd_soc_dapm_kcontrol_dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static void dapm_reset(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) lockdep_assert_held(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) for_each_card_widgets(card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) w->new_power = w->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) w->power_checked = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) static const char *soc_dapm_prefix(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (!dapm->component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return dapm->component->name_prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (!dapm->component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return snd_soc_component_read(dapm->component, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static int soc_dapm_update_bits(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) int reg, unsigned int mask, unsigned int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (!dapm->component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return snd_soc_component_update_bits(dapm->component, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) mask, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static int soc_dapm_test_bits(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int reg, unsigned int mask, unsigned int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (!dapm->component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return snd_soc_component_test_bits(dapm->component, reg, mask, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (dapm->component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) snd_soc_component_async_complete(dapm->component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static struct snd_soc_dapm_widget *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct snd_soc_dapm_widget *w = wcache->widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) struct list_head *wlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) const int depth = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) wlist = &w->dapm->card->widgets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) list_for_each_entry_from(w, wlist, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (!strcmp(name, w->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (++i == depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static inline void dapm_wcache_update(struct snd_soc_dapm_wcache *wcache,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) wcache->widget = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * snd_soc_dapm_force_bias_level() - Sets the DAPM bias level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * @dapm: The DAPM context for which to set the level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * @level: The level to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * Forces the DAPM bias level to a specific state. It will call the bias level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * callback of DAPM context with the specified level. This will even happen if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * the context is already at the same level. Furthermore it will not go through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * the normal bias level sequencing, meaning any intermediate states between the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * current and the target state will not be entered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * Note that the change in bias level is only temporary and the next time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * snd_soc_dapm_sync() is called the state will be set to the level as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * determined by the DAPM core. The function is mainly intended to be used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * used during probe or resume from suspend to power up the device so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * initialization can be done, before the DAPM core takes over.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) enum snd_soc_bias_level level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (dapm->component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = snd_soc_component_set_bias_level(dapm->component, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) dapm->bias_level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) EXPORT_SYMBOL_GPL(snd_soc_dapm_force_bias_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * snd_soc_dapm_set_bias_level - set the bias level for the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * @level: level to configure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * Configure the bias (power) levels for the SoC audio device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * Returns 0 for success else error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) enum snd_soc_bias_level level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) trace_snd_soc_bias_level_start(card, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) ret = snd_soc_card_set_bias_level(card, dapm, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (!card || dapm != &card->dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) ret = snd_soc_dapm_force_bias_level(dapm, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) ret = snd_soc_card_set_bias_level_post(card, dapm, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) trace_snd_soc_bias_level_done(card, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* connect mux widget to its interconnecting audio paths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct snd_soc_dapm_path *path, const char *control_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) const struct snd_kcontrol_new *kcontrol = &w->kcontrol_news[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) unsigned int val, item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (e->reg != SND_SOC_NOPM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) val = soc_dapm_read(dapm, e->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) val = (val >> e->shift_l) & e->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) item = snd_soc_enum_val_to_item(e, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* since a virtual mux has no backing registers to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) * decide which path to connect, it will try to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * with the first enumeration. This is to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * that the default mux choice (the first) will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * correctly powered up during initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) item = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) i = match_string(e->texts, e->items, control_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (i < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) path->name = e->texts[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) path->connect = (i == item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* set up initial codec paths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) int nth_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct soc_mixer_control *mc = (struct soc_mixer_control *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) p->sink->kcontrol_news[i].private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) unsigned int reg = mc->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) unsigned int shift = mc->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) unsigned int max = mc->max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) unsigned int mask = (1 << fls(max)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) unsigned int invert = mc->invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (reg != SND_SOC_NOPM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) val = soc_dapm_read(p->sink->dapm, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * The nth_path argument allows this function to know
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * which path of a kcontrol it is setting the initial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * status for. Ideally this would support any number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * of paths and channels. But since kcontrols only come
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * in mono and stereo variants, we are limited to 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * The following code assumes for stereo controls the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * first path is the left channel, and all remaining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * paths are the right channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (snd_soc_volsw_is_stereo(mc) && nth_path > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (reg != mc->rreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) val = soc_dapm_read(p->sink->dapm, mc->rreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) val = (val >> mc->rshift) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) val = (val >> shift) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) val = max - val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) p->connect = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* since a virtual mixer has no backing registers to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * decide which path to connect, it will try to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * with initial state. This is to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * that the default mixer choice will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * correctly powered up during initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) p->connect = invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* connect mixer widget to its interconnecting audio paths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct snd_soc_dapm_path *path, const char *control_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) int i, nth_path = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) /* search for mixer kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) for (i = 0; i < path->sink->num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (!strcmp(control_name, path->sink->kcontrol_news[i].name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) path->name = path->sink->kcontrol_news[i].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) dapm_set_mixer_path_status(path, i, nth_path++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct snd_soc_dapm_widget *kcontrolw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) const struct snd_kcontrol_new *kcontrol_new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct snd_kcontrol **kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) *kcontrol = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) for_each_card_widgets(dapm->card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (w == kcontrolw || w->dapm != kcontrolw->dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) for (i = 0; i < w->num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (&w->kcontrol_news[i] == kcontrol_new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (w->kcontrols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) *kcontrol = w->kcontrols[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) * Determine if a kcontrol is shared. If it is, look it up. If it isn't,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * create it. Either way, add the widget into the control's widget list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int dapm_create_or_share_kcontrol(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) int kci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct snd_soc_dapm_context *dapm = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct snd_card *card = dapm->card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) const char *prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) size_t prefix_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) int shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct snd_kcontrol *kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) bool wname_in_long_name, kcname_in_long_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) char *long_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) prefix = soc_dapm_prefix(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) prefix_len = strlen(prefix) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) prefix_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) shared = dapm_is_shared_kcontrol(dapm, w, &w->kcontrol_news[kci],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) &kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (!kcontrol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (shared) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) wname_in_long_name = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) kcname_in_long_name = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) case snd_soc_dapm_switch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) case snd_soc_dapm_mixer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) case snd_soc_dapm_pga:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) case snd_soc_dapm_effect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) case snd_soc_dapm_out_drv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) wname_in_long_name = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) kcname_in_long_name = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) case snd_soc_dapm_mixer_named_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) wname_in_long_name = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) kcname_in_long_name = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) case snd_soc_dapm_demux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) case snd_soc_dapm_mux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) wname_in_long_name = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) kcname_in_long_name = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (wname_in_long_name && kcname_in_long_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * The control will get a prefix from the control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * creation process but we're also using the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * prefix for widgets so cut the prefix off the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * front of the widget name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) long_name = kasprintf(GFP_KERNEL, "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) w->name + prefix_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) w->kcontrol_news[kci].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (long_name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) name = long_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) } else if (wname_in_long_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) long_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) name = w->name + prefix_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) long_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) name = w->kcontrol_news[kci].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (!kcontrol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) goto exit_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) kcontrol->private_free = dapm_kcontrol_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ret = dapm_kcontrol_data_alloc(w, kcontrol, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) snd_ctl_free_one(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) goto exit_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) ret = snd_ctl_add(card, kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) "ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) w->name, name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) goto exit_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) ret = dapm_kcontrol_add_widget(kcontrol, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) w->kcontrols[kci] = kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) exit_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) kfree(long_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* create new dapm mixer control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) struct dapm_kcontrol_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* add kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) for (i = 0; i < w->num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /* match name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) snd_soc_dapm_widget_for_each_source_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) /* mixer/mux paths name must match control name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (path->name != (char *)w->kcontrol_news[i].name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (!w->kcontrols[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) ret = dapm_create_or_share_kcontrol(w, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) dapm_kcontrol_add_path(w->kcontrols[i], path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) data = snd_kcontrol_chip(w->kcontrols[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (data->widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) snd_soc_dapm_add_path(data->widget->dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) data->widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) path->source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* create new dapm mux control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) static int dapm_new_mux(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) struct snd_soc_dapm_context *dapm = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) enum snd_soc_dapm_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) const char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) case snd_soc_dapm_mux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) dir = SND_SOC_DAPM_DIR_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) type = "mux";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) case snd_soc_dapm_demux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) dir = SND_SOC_DAPM_DIR_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) type = "demux";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (w->num_kcontrols != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) "ASoC: %s %s has incorrect number of controls\n", type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) w->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (list_empty(&w->edges[dir])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) dev_err(dapm->dev, "ASoC: %s %s has no paths\n", type, w->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) ret = dapm_create_or_share_kcontrol(w, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) snd_soc_dapm_widget_for_each_path(w, dir, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (path->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) dapm_kcontrol_add_path(w->kcontrols[0], path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* create new dapm volume control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static int dapm_new_pga(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) for (i = 0; i < w->num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) ret = dapm_create_or_share_kcontrol(w, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) /* create new dapm dai link control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) static int dapm_new_dai_link(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) struct snd_kcontrol *kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) struct snd_soc_dapm_context *dapm = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) struct snd_card *card = dapm->card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct snd_soc_pcm_runtime *rtd = w->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /* create control for links with > 1 config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (rtd->dai_link->num_params <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) /* add kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) for (i = 0; i < w->num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) kcontrol = snd_soc_cnew(&w->kcontrol_news[i], w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) w->name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ret = snd_ctl_add(card, kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) "ASoC: failed to add widget %s dapm kcontrol %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) w->name, w->kcontrol_news[i].name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) kcontrol->private_data = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) w->kcontrols[i] = kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /* We implement power down on suspend by checking the power state of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * the ALSA card - when we are suspending the ALSA state for the card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * is set to D3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) int level = snd_power_get_state(widget->dapm->card->snd_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) switch (level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) case SNDRV_CTL_POWER_D3hot:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) case SNDRV_CTL_POWER_D3cold:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (widget->ignore_suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) dev_dbg(widget->dapm->dev, "ASoC: %s ignoring suspend\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) widget->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return widget->ignore_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) static void dapm_widget_list_free(struct snd_soc_dapm_widget_list **list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) kfree(*list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) struct list_head *widgets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct list_head *it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) unsigned int size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) unsigned int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) list_for_each(it, widgets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) size++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) *list = kzalloc(struct_size(*list, widgets, size), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (*list == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) list_for_each_entry(w, widgets, work_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) (*list)->widgets[i++] = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) (*list)->num_widgets = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) * Recursively reset the cached number of inputs or outputs for the specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * widget and all widgets that can be reached via incoming or outcoming paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * from the widget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) static void invalidate_paths_ep(struct snd_soc_dapm_widget *widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) enum snd_soc_dapm_direction dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) widget->endpoints[dir] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) snd_soc_dapm_widget_for_each_path(widget, rdir, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (path->weak || path->is_supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (path->walking)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (path->connect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) path->walking = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) invalidate_paths_ep(path->node[dir], dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) path->walking = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) * Common implementation for is_connected_output_ep() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) * is_connected_input_ep(). The function is inlined since the combined size of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) * the two specialized functions is only marginally larger then the size of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) * generic function and at the same time the fast path of the specialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) * functions is significantly smaller than the generic function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) static __always_inline int is_connected_ep(struct snd_soc_dapm_widget *widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) struct list_head *list, enum snd_soc_dapm_direction dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) int (*fn)(struct snd_soc_dapm_widget *, struct list_head *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) enum snd_soc_dapm_direction)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) enum snd_soc_dapm_direction))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) enum snd_soc_dapm_direction rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) int con = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (widget->endpoints[dir] >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return widget->endpoints[dir];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) DAPM_UPDATE_STAT(widget, path_checks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /* do we need to add this widget to the list ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) list_add_tail(&widget->work_list, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (custom_stop_condition && custom_stop_condition(widget, dir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) list = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) custom_stop_condition = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if ((widget->is_ep & SND_SOC_DAPM_DIR_TO_EP(dir)) && widget->connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) widget->endpoints[dir] = snd_soc_dapm_suspend_check(widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return widget->endpoints[dir];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) snd_soc_dapm_widget_for_each_path(widget, rdir, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) DAPM_UPDATE_STAT(widget, neighbour_checks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (path->weak || path->is_supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (path->walking)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) trace_snd_soc_dapm_path(widget, dir, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (path->connect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) path->walking = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) con += fn(path->node[dir], list, custom_stop_condition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) path->walking = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) widget->endpoints[dir] = con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) return con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * Recursively check for a completed path to an active or physically connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) * output widget. Returns number of complete paths.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * Optionally, can be supplied with a function acting as a stopping condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) * This function takes the dapm widget currently being examined and the walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) * direction as an arguments, it should return true if widgets from that point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) * in the graph onwards should not be added to the widget list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) struct list_head *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) bool (*custom_stop_condition)(struct snd_soc_dapm_widget *i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) enum snd_soc_dapm_direction))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) return is_connected_ep(widget, list, SND_SOC_DAPM_DIR_OUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) is_connected_output_ep, custom_stop_condition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * Recursively check for a completed path to an active or physically connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) * input widget. Returns number of complete paths.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * Optionally, can be supplied with a function acting as a stopping condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * This function takes the dapm widget currently being examined and the walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * direction as an arguments, it should return true if the walk should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) * stopped and false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) struct list_head *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) bool (*custom_stop_condition)(struct snd_soc_dapm_widget *i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) enum snd_soc_dapm_direction))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return is_connected_ep(widget, list, SND_SOC_DAPM_DIR_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) is_connected_input_ep, custom_stop_condition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) * snd_soc_dapm_dai_get_connected_widgets - query audio path and it's widgets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) * @dai: the soc DAI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) * @stream: stream direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) * @list: list of active widgets for this stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) * @custom_stop_condition: (optional) a function meant to stop the widget graph
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * walk based on custom logic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * Queries DAPM graph as to whether a valid audio stream path exists for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) * the initial stream specified by name. This takes into account
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) * current mixer and mux kcontrol settings. Creates list of valid widgets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) * Optionally, can be supplied with a function acting as a stopping condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) * This function takes the dapm widget currently being examined and the walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) * direction as an arguments, it should return true if the walk should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) * stopped and false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) * Returns the number of valid paths or negative error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) struct snd_soc_dapm_widget_list **list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) bool (*custom_stop_condition)(struct snd_soc_dapm_widget *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) enum snd_soc_dapm_direction))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) struct snd_soc_card *card = dai->component->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) LIST_HEAD(widgets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) int paths;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) w = dai->playback_widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) invalidate_paths_ep(w, SND_SOC_DAPM_DIR_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) paths = is_connected_output_ep(w, &widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) custom_stop_condition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) w = dai->capture_widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) invalidate_paths_ep(w, SND_SOC_DAPM_DIR_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) paths = is_connected_input_ep(w, &widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) custom_stop_condition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) /* Drop starting point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) list_del(widgets.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) ret = dapm_widget_list_create(list, &widgets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) paths = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) trace_snd_soc_dapm_connected(paths, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) return paths;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) dapm_widget_list_free(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * Handler for regulator supply widget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) int dapm_regulator_event(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) struct snd_kcontrol *kcontrol, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) soc_dapm_async_complete(w->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (SND_SOC_DAPM_EVENT_ON(event)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) ret = regulator_allow_bypass(w->regulator, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) dev_warn(w->dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) "ASoC: Failed to unbypass %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) return regulator_enable(w->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) ret = regulator_allow_bypass(w->regulator, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) dev_warn(w->dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) "ASoC: Failed to bypass %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return regulator_disable_deferred(w->regulator, w->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) EXPORT_SYMBOL_GPL(dapm_regulator_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) * Handler for pinctrl widget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) int dapm_pinctrl_event(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) struct snd_kcontrol *kcontrol, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) struct snd_soc_dapm_pinctrl_priv *priv = w->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) struct pinctrl *p = w->pinctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) struct pinctrl_state *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (!p || !priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) if (SND_SOC_DAPM_EVENT_ON(event))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) s = pinctrl_lookup_state(p, priv->active_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) s = pinctrl_lookup_state(p, priv->sleep_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (IS_ERR(s))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return PTR_ERR(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) return pinctrl_select_state(p, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) EXPORT_SYMBOL_GPL(dapm_pinctrl_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * Handler for clock supply widget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) int dapm_clock_event(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) struct snd_kcontrol *kcontrol, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (!w->clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) soc_dapm_async_complete(w->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (SND_SOC_DAPM_EVENT_ON(event)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) return clk_prepare_enable(w->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) clk_disable_unprepare(w->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) EXPORT_SYMBOL_GPL(dapm_clock_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) if (w->power_checked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) return w->new_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) if (w->force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) w->new_power = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) w->new_power = w->power_check(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) w->power_checked = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) return w->new_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) /* Generic check to see if a widget should be powered. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) int in, out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) DAPM_UPDATE_STAT(w, power_checks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) in = is_connected_input_ep(w, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) out = is_connected_output_ep(w, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return out != 0 && in != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) /* Check to see if a power supply is needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) DAPM_UPDATE_STAT(w, power_checks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) /* Check if one of our outputs is connected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) snd_soc_dapm_widget_for_each_sink_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) DAPM_UPDATE_STAT(w, neighbour_checks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if (path->weak)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) if (path->connected &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) !path->connected(path->source, path->sink))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (dapm_widget_power_check(path->sink))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) return w->connected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) struct snd_soc_dapm_widget *b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) bool power_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) int *sort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) BUILD_BUG_ON(ARRAY_SIZE(dapm_up_seq) != SND_SOC_DAPM_TYPE_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) BUILD_BUG_ON(ARRAY_SIZE(dapm_down_seq) != SND_SOC_DAPM_TYPE_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) if (power_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) sort = dapm_up_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) sort = dapm_down_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) WARN_ONCE(sort[a->id] == 0, "offset a->id %d not initialized\n", a->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) WARN_ONCE(sort[b->id] == 0, "offset b->id %d not initialized\n", b->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) if (sort[a->id] != sort[b->id])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) return sort[a->id] - sort[b->id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (a->subseq != b->subseq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) if (power_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) return a->subseq - b->subseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) return b->subseq - a->subseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) if (a->reg != b->reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return a->reg - b->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (a->dapm != b->dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) return (unsigned long)a->dapm - (unsigned long)b->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) /* Insert a widget in order into a DAPM power sequence. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) struct list_head *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) bool power_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) list_for_each_entry(w, list, power_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) if (dapm_seq_compare(new_widget, w, power_up) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) list_add_tail(&new_widget->power_list, &w->power_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) list_add_tail(&new_widget->power_list, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) static void dapm_seq_check_event(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) struct snd_soc_dapm_widget *w, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) const char *ev_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) int power, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) case SND_SOC_DAPM_PRE_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) ev_name = "PRE_PMU";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) power = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) case SND_SOC_DAPM_POST_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) ev_name = "POST_PMU";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) power = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) case SND_SOC_DAPM_PRE_PMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) ev_name = "PRE_PMD";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) power = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) case SND_SOC_DAPM_POST_PMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) ev_name = "POST_PMD";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) power = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) case SND_SOC_DAPM_WILL_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) ev_name = "WILL_PMU";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) power = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) case SND_SOC_DAPM_WILL_PMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) ev_name = "WILL_PMD";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) power = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) WARN(1, "Unknown event %d\n", event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) if (w->new_power != power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (w->event && (w->event_flags & event)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) w->name, ev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) soc_dapm_async_complete(w->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) trace_snd_soc_dapm_widget_event_start(w, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) ret = w->event(w, NULL, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) trace_snd_soc_dapm_widget_event_done(w, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) dev_err(w->dapm->dev, "ASoC: %s: %s event failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) ev_name, w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) /* Apply the coalesced changes from a DAPM sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) static void dapm_seq_run_coalesced(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) struct list_head *pending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) struct snd_soc_dapm_context *dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) unsigned int value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) unsigned int mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) w = list_first_entry(pending, struct snd_soc_dapm_widget, power_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) reg = w->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) dapm = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) list_for_each_entry(w, pending, power_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) WARN_ON(reg != w->reg || dapm != w->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) w->power = w->new_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) mask |= w->mask << w->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) if (w->power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) value |= w->on_val << w->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) value |= w->off_val << w->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) pop_dbg(dapm->dev, card->pop_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) w->name, reg, value, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) /* Check for events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) dapm_seq_check_event(card, w, SND_SOC_DAPM_PRE_PMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if (reg >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) /* Any widget will do, they should all be updating the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) * same register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) pop_dbg(dapm->dev, card->pop_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) "pop test : Applying 0x%x/0x%x to %x in %dms\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) value, mask, reg, card->pop_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) pop_wait(card->pop_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) soc_dapm_update_bits(dapm, reg, mask, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) list_for_each_entry(w, pending, power_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) dapm_seq_check_event(card, w, SND_SOC_DAPM_POST_PMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) /* Apply a DAPM power sequence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) * We walk over a pre-sorted list of widgets to apply power to. In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) * order to minimise the number of writes to the device required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) * multiple widgets will be updated in a single write where possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) * Currently anything that requires more than a single write is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) * handled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) static void dapm_seq_run(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) struct list_head *list, int event, bool power_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) struct snd_soc_dapm_widget *w, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) struct snd_soc_dapm_context *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) LIST_HEAD(pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) int cur_sort = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) int cur_subseq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) int cur_reg = SND_SOC_NOPM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) struct snd_soc_dapm_context *cur_dapm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) int *sort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (power_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) sort = dapm_up_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) sort = dapm_down_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) list_for_each_entry_safe(w, n, list, power_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /* Do we need to apply any queued changes? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) if (sort[w->id] != cur_sort || w->reg != cur_reg ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) w->dapm != cur_dapm || w->subseq != cur_subseq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if (!list_empty(&pending))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) dapm_seq_run_coalesced(card, &pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) if (cur_dapm && cur_dapm->component) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (sort[i] == cur_sort)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) snd_soc_component_seq_notifier(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) cur_dapm->component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) i, cur_subseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) if (cur_dapm && w->dapm != cur_dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) soc_dapm_async_complete(cur_dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) INIT_LIST_HEAD(&pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) cur_sort = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) cur_subseq = INT_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) cur_reg = SND_SOC_NOPM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) cur_dapm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) case snd_soc_dapm_pre:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) if (!w->event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) list_for_each_entry_safe_continue(w, n, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) power_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) if (event == SND_SOC_DAPM_STREAM_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) ret = w->event(w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) NULL, SND_SOC_DAPM_PRE_PMU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) else if (event == SND_SOC_DAPM_STREAM_STOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) ret = w->event(w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) NULL, SND_SOC_DAPM_PRE_PMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) case snd_soc_dapm_post:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) if (!w->event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) list_for_each_entry_safe_continue(w, n, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) power_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) if (event == SND_SOC_DAPM_STREAM_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) ret = w->event(w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) NULL, SND_SOC_DAPM_POST_PMU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) else if (event == SND_SOC_DAPM_STREAM_STOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) ret = w->event(w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) NULL, SND_SOC_DAPM_POST_PMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) /* Queue it up for application */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) cur_sort = sort[w->id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) cur_subseq = w->subseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) cur_reg = w->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) cur_dapm = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) list_move(&w->power_list, &pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) dev_err(w->dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) "ASoC: Failed to apply widget power: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) if (!list_empty(&pending))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) dapm_seq_run_coalesced(card, &pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) if (cur_dapm && cur_dapm->component) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (sort[i] == cur_sort)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) snd_soc_component_seq_notifier(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) cur_dapm->component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) i, cur_subseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) for_each_card_dapms(card, d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) soc_dapm_async_complete(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) static void dapm_widget_update(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) struct snd_soc_dapm_update *update = card->update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) struct snd_soc_dapm_widget_list *wlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) struct snd_soc_dapm_widget *w = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) unsigned int wi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) if (!update || !dapm_kcontrol_is_powered(update->kcontrol))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) wlist = dapm_kcontrol_get_wlist(update->kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) for_each_dapm_widgets(wlist, wi, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) if (w->event && (w->event_flags & SND_SOC_DAPM_PRE_REG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) ret = w->event(w, update->kcontrol, SND_SOC_DAPM_PRE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) dev_err(w->dapm->dev, "ASoC: %s DAPM pre-event failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) if (!w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) ret = soc_dapm_update_bits(w->dapm, update->reg, update->mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) update->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) if (update->has_second_set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) ret = soc_dapm_update_bits(w->dapm, update->reg2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) update->mask2, update->val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) dev_err(w->dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) "ASoC: %s DAPM update failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) for_each_dapm_widgets(wlist, wi, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) if (w->event && (w->event_flags & SND_SOC_DAPM_POST_REG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) ret = w->event(w, update->kcontrol, SND_SOC_DAPM_POST_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) dev_err(w->dapm->dev, "ASoC: %s DAPM post-event failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) /* Async callback run prior to DAPM sequences - brings to _PREPARE if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) * they're changing state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) struct snd_soc_dapm_context *d = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) /* If we're off and we're not supposed to go into STANDBY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) if (d->bias_level == SND_SOC_BIAS_OFF &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) d->target_bias_level != SND_SOC_BIAS_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) if (d->dev && cookie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) pm_runtime_get_sync(d->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) dev_err(d->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) "ASoC: Failed to turn on bias: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) /* Prepare for a transition to ON or away from ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) if ((d->target_bias_level == SND_SOC_BIAS_ON &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) d->bias_level != SND_SOC_BIAS_ON) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) (d->target_bias_level != SND_SOC_BIAS_ON &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) d->bias_level == SND_SOC_BIAS_ON)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) dev_err(d->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) "ASoC: Failed to prepare bias: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) /* Async callback run prior to DAPM sequences - brings to their final
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) * state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) struct snd_soc_dapm_context *d = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) /* If we just powered the last thing off drop to standby bias */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) if (d->bias_level == SND_SOC_BIAS_PREPARE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) (d->target_bias_level == SND_SOC_BIAS_STANDBY ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) d->target_bias_level == SND_SOC_BIAS_OFF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) dev_err(d->dev, "ASoC: Failed to apply standby bias: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) /* If we're in standby and can support bias off then do that */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) if (d->bias_level == SND_SOC_BIAS_STANDBY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) d->target_bias_level == SND_SOC_BIAS_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) dev_err(d->dev, "ASoC: Failed to turn off bias: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) if (d->dev && cookie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) pm_runtime_put(d->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) /* If we just powered up then move to active bias */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) if (d->bias_level == SND_SOC_BIAS_PREPARE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) d->target_bias_level == SND_SOC_BIAS_ON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) dev_err(d->dev, "ASoC: Failed to apply active bias: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) static void dapm_widget_set_peer_power(struct snd_soc_dapm_widget *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) bool power, bool connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) /* If a connection is being made or broken then that update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) * will have marked the peer dirty, otherwise the widgets are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) * not connected and this update has no impact. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) if (!connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) /* If the peer is already in the state we're moving to then we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) * won't have an impact on it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) if (power != peer->power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) dapm_mark_dirty(peer, "peer state change");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) struct list_head *up_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) struct list_head *down_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) if (w->power == power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) trace_snd_soc_dapm_widget_power(w, power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) /* If we changed our power state perhaps our neigbours changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) * also.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) snd_soc_dapm_widget_for_each_source_path(w, path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) dapm_widget_set_peer_power(path->source, power, path->connect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) /* Supplies can't affect their outputs, only their inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) if (!w->is_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) snd_soc_dapm_widget_for_each_sink_path(w, path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) dapm_widget_set_peer_power(path->sink, power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) path->connect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) if (power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) dapm_seq_insert(w, up_list, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) dapm_seq_insert(w, down_list, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) struct list_head *up_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) struct list_head *down_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) int power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) case snd_soc_dapm_pre:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) dapm_seq_insert(w, down_list, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) case snd_soc_dapm_post:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) dapm_seq_insert(w, up_list, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) power = dapm_widget_power_check(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) dapm_widget_set_power(w, power, up_list, down_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) if (dapm->idle_bias_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) switch (snd_power_get_state(dapm->card->snd_card)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) case SNDRV_CTL_POWER_D3hot:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) case SNDRV_CTL_POWER_D3cold:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) return dapm->suspend_bias_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) * Scan each dapm widget for complete audio path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) * A complete path is a route that has valid endpoints i.e.:-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) * o DAC to output pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) * o Input pin to ADC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) * o Input pin to Output pin (bypass, sidetone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) * o DAC to ADC (loopback).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) static int dapm_power_widgets(struct snd_soc_card *card, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) struct snd_soc_dapm_context *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) LIST_HEAD(up_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) LIST_HEAD(down_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) ASYNC_DOMAIN_EXCLUSIVE(async_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) enum snd_soc_bias_level bias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) lockdep_assert_held(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) trace_snd_soc_dapm_start(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) for_each_card_dapms(card, d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) if (dapm_idle_bias_off(d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) d->target_bias_level = SND_SOC_BIAS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) d->target_bias_level = SND_SOC_BIAS_STANDBY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) dapm_reset(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) /* Check which widgets we need to power and store them in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) * lists indicating if they should be powered up or down. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) * only check widgets that have been flagged as dirty but note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) * that new widgets may be added to the dirty list while we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) * iterate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) list_for_each_entry(w, &card->dapm_dirty, dirty) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) dapm_power_one_widget(w, &up_list, &down_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) for_each_card_widgets(card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) case snd_soc_dapm_pre:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) case snd_soc_dapm_post:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) /* These widgets always need to be powered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) list_del_init(&w->dirty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) if (w->new_power) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) d = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) /* Supplies and micbiases only bring the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) * context up to STANDBY as unless something
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) * else is active and passing audio they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) * generally don't require full power. Signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) * generators are virtual pins and have no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) * power impact themselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) case snd_soc_dapm_siggen:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) case snd_soc_dapm_vmid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) case snd_soc_dapm_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) case snd_soc_dapm_regulator_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) case snd_soc_dapm_pinctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) case snd_soc_dapm_clock_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) case snd_soc_dapm_micbias:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) d->target_bias_level = SND_SOC_BIAS_STANDBY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) d->target_bias_level = SND_SOC_BIAS_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) /* Force all contexts in the card to the same bias state if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) * they're not ground referenced.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) bias = SND_SOC_BIAS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) for_each_card_dapms(card, d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) if (d->target_bias_level > bias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) bias = d->target_bias_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) for_each_card_dapms(card, d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) if (!dapm_idle_bias_off(d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) d->target_bias_level = bias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) trace_snd_soc_dapm_walk_done(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) /* Run card bias changes at first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) dapm_pre_sequence_async(&card->dapm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) /* Run other bias changes in parallel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) for_each_card_dapms(card, d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) if (d != &card->dapm && d->bias_level != d->target_bias_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) async_schedule_domain(dapm_pre_sequence_async, d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) &async_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) async_synchronize_full_domain(&async_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) list_for_each_entry(w, &down_list, power_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) list_for_each_entry(w, &up_list, power_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) dapm_seq_check_event(card, w, SND_SOC_DAPM_WILL_PMU);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) /* Power down widgets first; try to avoid amplifying pops. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) dapm_seq_run(card, &down_list, event, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) dapm_widget_update(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) /* Now power up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) dapm_seq_run(card, &up_list, event, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) /* Run all the bias changes in parallel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) for_each_card_dapms(card, d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) if (d != &card->dapm && d->bias_level != d->target_bias_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) async_schedule_domain(dapm_post_sequence_async, d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) &async_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) async_synchronize_full_domain(&async_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) /* Run card bias changes at last */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) dapm_post_sequence_async(&card->dapm, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) /* do we need to notify any clients that DAPM event is complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) for_each_card_dapms(card, d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) if (!d->component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) ret = snd_soc_component_stream_event(d->component, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) pop_dbg(card->dev, card->pop_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) "DAPM sequencing finished, waiting %dms\n", card->pop_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) pop_wait(card->pop_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) trace_snd_soc_dapm_done(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) static ssize_t dapm_widget_power_read_file(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) struct snd_soc_dapm_widget *w = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) struct snd_soc_card *card = w->dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) enum snd_soc_dapm_direction dir, rdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) int in, out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) struct snd_soc_dapm_path *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) mutex_lock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) /* Supply widgets are not handled by is_connected_{input,output}_ep() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) if (w->is_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) in = is_connected_input_ep(w, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) out = is_connected_output_ep(w, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) ret = scnprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) w->name, w->power ? "On" : "Off",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) w->force ? " (forced)" : "", in, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) if (w->reg >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) ret += scnprintf(buf + ret, PAGE_SIZE - ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) " - R%d(0x%x) mask 0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) w->reg, w->reg, w->mask << w->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) if (w->sname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) ret += scnprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) w->sname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) w->active ? "active" : "inactive");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) snd_soc_dapm_for_each_direction(dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) rdir = SND_SOC_DAPM_DIR_REVERSE(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) snd_soc_dapm_widget_for_each_path(w, dir, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) if (p->connected && !p->connected(p->source, p->sink))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) if (!p->connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) ret += scnprintf(buf + ret, PAGE_SIZE - ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) " %s \"%s\" \"%s\"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) (rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) p->name ? p->name : "static",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) p->node[rdir]->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) static const struct file_operations dapm_widget_power_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) .open = simple_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) .read = dapm_widget_power_read_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) struct snd_soc_dapm_context *dapm = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) char *level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) switch (dapm->bias_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) case SND_SOC_BIAS_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) level = "On\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) case SND_SOC_BIAS_PREPARE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) level = "Prepare\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) case SND_SOC_BIAS_STANDBY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) level = "Standby\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) case SND_SOC_BIAS_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) level = "Off\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) WARN(1, "Unknown bias_level %d\n", dapm->bias_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) level = "Unknown\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) return simple_read_from_buffer(user_buf, count, ppos, level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) strlen(level));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) static const struct file_operations dapm_bias_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) .open = simple_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) .read = dapm_bias_read_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) struct dentry *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) if (!parent || IS_ERR(parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) debugfs_create_file("bias_level", 0444, dapm->debugfs_dapm, dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) &dapm_bias_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) static void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) struct snd_soc_dapm_context *dapm = w->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) if (!dapm->debugfs_dapm || !w->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) debugfs_create_file(w->name, 0444, dapm->debugfs_dapm, w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) &dapm_widget_power_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) debugfs_remove_recursive(dapm->debugfs_dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) dapm->debugfs_dapm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) struct dentry *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) static inline void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) * soc_dapm_connect_path() - Connects or disconnects a path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) * @path: The path to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) * @connect: The new connect state of the path. True if the path is connected,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) * false if it is disconnected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) * @reason: The reason why the path changed (for debugging only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) static void soc_dapm_connect_path(struct snd_soc_dapm_path *path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) bool connect, const char *reason)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) if (path->connect == connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) path->connect = connect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) dapm_mark_dirty(path->source, reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) dapm_mark_dirty(path->sink, reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) dapm_path_invalidate(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) /* test and update the power status of a mux widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) static int soc_dapm_mux_update_power(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) int found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) bool connect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) lockdep_assert_held(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) /* find dapm widget path assoc with kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) dapm_kcontrol_for_each_path(path, kcontrol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) /* we now need to match the string in the enum to the path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) if (e && !(strcmp(path->name, e->texts[mux])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) connect = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) connect = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) soc_dapm_connect_path(path, connect, "mux update");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) struct snd_soc_dapm_update *update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) card->update = update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) ret = soc_dapm_mux_update_power(card, kcontrol, mux, e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) card->update = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) snd_soc_dpcm_runtime_update(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) /* test and update the power status of a mixer or switch widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) int connect, int rconnect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) int found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) lockdep_assert_held(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) /* find dapm widget path assoc with kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) dapm_kcontrol_for_each_path(path, kcontrol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) * Ideally this function should support any number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) * paths and channels. But since kcontrols only come
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) * in mono and stereo variants, we are limited to 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) * channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) * The following code assumes for stereo controls the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) * first path (when 'found == 0') is the left channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) * and all remaining paths (when 'found == 1') are the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) * right channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) * A stereo control is signified by a valid 'rconnect'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) * value, either 0 for unconnected, or >= 0 for connected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) * This is chosen instead of using snd_soc_volsw_is_stereo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) * so that the behavior of snd_soc_dapm_mixer_update_power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) * doesn't change even when the kcontrol passed in is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) * stereo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) * It passes 'connect' as the path connect status for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) * the left channel, and 'rconnect' for the right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) * channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) if (found && rconnect >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) soc_dapm_connect_path(path, rconnect, "mixer update");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) soc_dapm_connect_path(path, connect, "mixer update");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) struct snd_kcontrol *kcontrol, int connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) struct snd_soc_dapm_update *update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) card->update = update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) ret = soc_dapm_mixer_update_power(card, kcontrol, connect, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) card->update = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) snd_soc_dpcm_runtime_update(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) static ssize_t dapm_widget_show_component(struct snd_soc_component *cmpnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) char *state = "not set";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) /* card won't be set for the dummy component, as a spot fix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) * we're checking for that case specifically here but in future
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) * we will ensure that the dummy component looks like others.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) if (!cmpnt->card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) for_each_card_widgets(cmpnt->card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) if (w->dapm != dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) /* only display widgets that burn power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) case snd_soc_dapm_hp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) case snd_soc_dapm_mic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) case snd_soc_dapm_spk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) case snd_soc_dapm_line:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) case snd_soc_dapm_micbias:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) case snd_soc_dapm_dac:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) case snd_soc_dapm_adc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) case snd_soc_dapm_pga:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) case snd_soc_dapm_effect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) case snd_soc_dapm_out_drv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) case snd_soc_dapm_mixer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) case snd_soc_dapm_mixer_named_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) case snd_soc_dapm_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) case snd_soc_dapm_regulator_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) case snd_soc_dapm_pinctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) case snd_soc_dapm_clock_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) if (w->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) count += sprintf(buf + count, "%s: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) w->name, w->power ? "On":"Off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) switch (snd_soc_dapm_get_bias_level(dapm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) case SND_SOC_BIAS_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) state = "On";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) case SND_SOC_BIAS_PREPARE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) state = "Prepare";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) case SND_SOC_BIAS_STANDBY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) state = "Standby";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) case SND_SOC_BIAS_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) state = "Off";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) count += sprintf(buf + count, "PM State: %s\n", state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) /* show dapm widget status in sys fs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) static ssize_t dapm_widget_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) struct snd_soc_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) int i, count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) mutex_lock(&rtd->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) for_each_rtd_codec_dais(rtd, i, codec_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) struct snd_soc_component *cmpnt = codec_dai->component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) count += dapm_widget_show_component(cmpnt, buf + count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) mutex_unlock(&rtd->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) static DEVICE_ATTR_RO(dapm_widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) struct attribute *soc_dapm_dev_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) &dev_attr_dapm_widget.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) static void dapm_free_path(struct snd_soc_dapm_path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) list_del(&path->list_node[SND_SOC_DAPM_DIR_IN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) list_del(&path->list_node[SND_SOC_DAPM_DIR_OUT]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) list_del(&path->list_kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) list_del(&path->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) kfree(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) struct snd_soc_dapm_path *p, *next_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) enum snd_soc_dapm_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) list_del(&w->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) list_del(&w->dirty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) * remove source and sink paths associated to this widget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) * While removing the path, remove reference to it from both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) * source and sink widgets so that path is removed only once.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) snd_soc_dapm_for_each_direction(dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) snd_soc_dapm_widget_for_each_path_safe(w, dir, p, next_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) dapm_free_path(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) kfree(w->kcontrols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) kfree_const(w->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) kfree_const(w->sname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) kfree(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) void snd_soc_dapm_reset_cache(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) dapm->path_sink_cache.widget = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) dapm->path_source_cache.widget = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) /* free all dapm widgets and resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) struct snd_soc_dapm_widget *w, *next_w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) for_each_card_widgets_safe(dapm->card, w, next_w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) if (w->dapm != dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) snd_soc_dapm_free_widget(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) snd_soc_dapm_reset_cache(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) static struct snd_soc_dapm_widget *dapm_find_widget(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) struct snd_soc_dapm_context *dapm, const char *pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) bool search_other_contexts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) struct snd_soc_dapm_widget *fallback = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) char prefixed_pin[80];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) const char *pin_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) const char *prefix = soc_dapm_prefix(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) if (prefix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) prefix, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) pin_name = prefixed_pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) pin_name = pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) for_each_card_widgets(dapm->card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) if (!strcmp(w->name, pin_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) if (w->dapm == dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) return w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) fallback = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) if (search_other_contexts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) return fallback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) * set the DAPM pin status:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) * returns 1 when the value has been updated, 0 when unchanged, or a negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) * error code; called from kcontrol put callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) static int __snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) const char *pin, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) dapm_assert_locked(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) if (!w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) dev_err(dapm->dev, "ASoC: DAPM unknown pin %s\n", pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) if (w->connected != status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) dapm_mark_dirty(w, "pin configuration");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) dapm_widget_invalidate_input_paths(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) dapm_widget_invalidate_output_paths(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) w->connected = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) if (status == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) w->force = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) * similar as __snd_soc_dapm_set_pin(), but returns 0 when successful;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) * called from several API functions below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) const char *pin, int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) int ret = __snd_soc_dapm_set_pin(dapm, pin, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) return ret < 0 ? ret : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) * snd_soc_dapm_sync_unlocked - scan and power dapm paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) * Walks all dapm audio paths and powers widgets according to their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) * stream or path usage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) * Requires external locking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) * Returns 0 for success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) * Suppress early reports (eg, jacks syncing their state) to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) * silly DAPM runs during card startup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) if (!dapm->card || !dapm->card->instantiated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) return dapm_power_widgets(dapm->card, SND_SOC_DAPM_STREAM_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) * snd_soc_dapm_sync - scan and power dapm paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) * Walks all dapm audio paths and powers widgets according to their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) * stream or path usage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) * Returns 0 for success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) ret = snd_soc_dapm_sync_unlocked(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) static int dapm_update_dai_chan(struct snd_soc_dapm_path *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) int channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) case snd_soc_dapm_aif_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) case snd_soc_dapm_aif_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) dev_dbg(w->dapm->dev, "%s DAI route %s -> %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) w->channel < channels ? "Connecting" : "Disconnecting",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) p->source->name, p->sink->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) if (w->channel < channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) soc_dapm_connect_path(p, true, "dai update");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) soc_dapm_connect_path(p, false, "dai update");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) static int dapm_update_dai_unlocked(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) int dir = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) int channels = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) struct snd_soc_dapm_path *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) w = snd_soc_dai_get_widget(dai, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) if (!w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) dev_dbg(dai->dev, "Update DAI routes for %s %s\n", dai->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) snd_soc_dapm_widget_for_each_sink_path(w, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) ret = dapm_update_dai_chan(p, p->sink, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) snd_soc_dapm_widget_for_each_source_path(w, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) ret = dapm_update_dai_chan(p, p->source, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) mutex_lock_nested(&rtd->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) ret = dapm_update_dai_unlocked(substream, params, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) mutex_unlock(&rtd->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) EXPORT_SYMBOL_GPL(snd_soc_dapm_update_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) * dapm_update_widget_flags() - Re-compute widget sink and source flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) * @w: The widget for which to update the flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) * Some widgets have a dynamic category which depends on which neighbors they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) * are connected to. This function update the category for these widgets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) * This function must be called whenever a path is added or removed to a widget.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) static void dapm_update_widget_flags(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) enum snd_soc_dapm_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) struct snd_soc_dapm_path *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) unsigned int ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) case snd_soc_dapm_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) /* On a fully routed card an input is never a source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) if (w->dapm->card->fully_routed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) ep = SND_SOC_DAPM_EP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) snd_soc_dapm_widget_for_each_source_path(w, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) if (p->source->id == snd_soc_dapm_micbias ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) p->source->id == snd_soc_dapm_mic ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) p->source->id == snd_soc_dapm_line ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) p->source->id == snd_soc_dapm_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) ep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) case snd_soc_dapm_output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) /* On a fully routed card a output is never a sink */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) if (w->dapm->card->fully_routed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) ep = SND_SOC_DAPM_EP_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) snd_soc_dapm_widget_for_each_sink_path(w, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) if (p->sink->id == snd_soc_dapm_spk ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) p->sink->id == snd_soc_dapm_hp ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) p->sink->id == snd_soc_dapm_line ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) p->sink->id == snd_soc_dapm_input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) ep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) case snd_soc_dapm_line:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) ep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) snd_soc_dapm_for_each_direction(dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) if (!list_empty(&w->edges[dir]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) ep |= SND_SOC_DAPM_DIR_TO_EP(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) w->is_ep = ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) static int snd_soc_dapm_check_dynamic_path(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *sink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) const char *control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) bool dynamic_source = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) bool dynamic_sink = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) if (!control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) switch (source->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) case snd_soc_dapm_demux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) dynamic_source = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) switch (sink->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) case snd_soc_dapm_mux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) case snd_soc_dapm_switch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) case snd_soc_dapm_mixer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) case snd_soc_dapm_mixer_named_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) dynamic_sink = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) if (dynamic_source && dynamic_sink) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) "Direct connection between demux and mixer/mux not supported for path %s -> [%s] -> %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) source->name, control, sink->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) } else if (!dynamic_source && !dynamic_sink) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) "Control not supported for path %s -> [%s] -> %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) source->name, control, sink->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) static int snd_soc_dapm_add_path(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) struct snd_soc_dapm_widget *wsource, struct snd_soc_dapm_widget *wsink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) const char *control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) int (*connected)(struct snd_soc_dapm_widget *source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) struct snd_soc_dapm_widget *sink))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) struct snd_soc_dapm_widget *widgets[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) enum snd_soc_dapm_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) if (wsink->is_supply && !wsource->is_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) "Connecting non-supply widget to supply widget is not supported (%s -> %s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) wsource->name, wsink->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) if (connected && !wsource->is_supply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) "connected() callback only supported for supply widgets (%s -> %s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) wsource->name, wsink->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) if (wsource->is_supply && control) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) "Conditional paths are not supported for supply widgets (%s -> [%s] -> %s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) wsource->name, control, wsink->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) ret = snd_soc_dapm_check_dynamic_path(dapm, wsource, wsink, control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) path->node[SND_SOC_DAPM_DIR_IN] = wsource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) path->node[SND_SOC_DAPM_DIR_OUT] = wsink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) widgets[SND_SOC_DAPM_DIR_IN] = wsource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) widgets[SND_SOC_DAPM_DIR_OUT] = wsink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) path->connected = connected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) INIT_LIST_HEAD(&path->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) INIT_LIST_HEAD(&path->list_kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) if (wsource->is_supply || wsink->is_supply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) path->is_supply = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) /* connect static paths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) if (control == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) path->connect = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) switch (wsource->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) case snd_soc_dapm_demux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) ret = dapm_connect_mux(dapm, path, control, wsource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) switch (wsink->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) case snd_soc_dapm_mux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) ret = dapm_connect_mux(dapm, path, control, wsink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) case snd_soc_dapm_switch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) case snd_soc_dapm_mixer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) case snd_soc_dapm_mixer_named_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) ret = dapm_connect_mixer(dapm, path, control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) list_add(&path->list, &dapm->card->paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) snd_soc_dapm_for_each_direction(dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) list_add(&path->list_node[dir], &widgets[dir]->edges[dir]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) snd_soc_dapm_for_each_direction(dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) dapm_update_widget_flags(widgets[dir]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) dapm_mark_dirty(widgets[dir], "Route added");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) if (dapm->card->instantiated && path->connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) dapm_path_invalidate(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) kfree(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) const struct snd_soc_dapm_route *route)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) struct snd_soc_dapm_widget *wtsource = NULL, *wtsink = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) const char *sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) const char *source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) char prefixed_sink[80];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) char prefixed_source[80];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) const char *prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) unsigned int sink_ref = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) unsigned int source_ref = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) prefix = soc_dapm_prefix(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) if (prefix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) prefix, route->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) sink = prefixed_sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) prefix, route->source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) source = prefixed_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) sink = route->sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) source = route->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) wsource = dapm_wcache_lookup(&dapm->path_source_cache, source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) wsink = dapm_wcache_lookup(&dapm->path_sink_cache, sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) if (wsink && wsource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) goto skip_search;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) * find src and dest widgets over all widgets but favor a widget from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) * current DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) for_each_card_widgets(dapm->card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) if (!wsink && !(strcmp(w->name, sink))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) wtsink = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) if (w->dapm == dapm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) wsink = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) if (wsource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) sink_ref++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) if (sink_ref > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) dev_warn(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) "ASoC: sink widget %s overwritten\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) w->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) if (!wsource && !(strcmp(w->name, source))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) wtsource = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) if (w->dapm == dapm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) wsource = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) if (wsink)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) source_ref++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) if (source_ref > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) dev_warn(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) "ASoC: source widget %s overwritten\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) w->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) /* use widget from another DAPM context if not found from this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) if (!wsink)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) wsink = wtsink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) if (!wsource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) wsource = wtsource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) if (wsource == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) dev_err(dapm->dev, "ASoC: no source widget found for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) route->source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) if (wsink == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) dev_err(dapm->dev, "ASoC: no sink widget found for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) route->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) skip_search:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) dapm_wcache_update(&dapm->path_sink_cache, wsink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) dapm_wcache_update(&dapm->path_source_cache, wsource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) ret = snd_soc_dapm_add_path(dapm, wsource, wsink, route->control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) route->connected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) dev_warn(dapm->dev, "ASoC: no dapm match for %s --> %s --> %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) source, route->control, sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) const struct snd_soc_dapm_route *route)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) struct snd_soc_dapm_widget *wsource, *wsink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) struct snd_soc_dapm_path *path, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) const char *sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) const char *source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) char prefixed_sink[80];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) char prefixed_source[80];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) const char *prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) if (route->control) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) dev_err(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) "ASoC: Removal of routes with controls not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) prefix = soc_dapm_prefix(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) if (prefix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) prefix, route->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) sink = prefixed_sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) snprintf(prefixed_source, sizeof(prefixed_source), "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) prefix, route->source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) source = prefixed_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) sink = route->sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) source = route->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) path = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) list_for_each_entry(p, &dapm->card->paths, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) if (strcmp(p->source->name, source) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) if (strcmp(p->sink->name, sink) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) path = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) if (path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) wsource = path->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) wsink = path->sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) dapm_mark_dirty(wsource, "Route removed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) dapm_mark_dirty(wsink, "Route removed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) if (path->connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) dapm_path_invalidate(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) dapm_free_path(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) /* Update any path related flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) dapm_update_widget_flags(wsource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) dapm_update_widget_flags(wsink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) dev_warn(dapm->dev, "ASoC: Route %s->%s does not exist\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) source, sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) * snd_soc_dapm_add_routes - Add routes between DAPM widgets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) * @route: audio routes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) * @num: number of routes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) * Connects 2 dapm widgets together via a named audio path. The sink is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) * the widget receiving the audio signal, whilst the source is the sender
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) * of the audio signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) * Returns 0 for success else error. On error all resources can be freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) * with a call to snd_soc_card_free().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) const struct snd_soc_dapm_route *route, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) int i, r, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) r = snd_soc_dapm_add_route(dapm, route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) if (r < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) route->source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) route->control ? route->control : "direct",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) route->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) ret = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) route++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) * snd_soc_dapm_del_routes - Remove routes between DAPM widgets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) * @route: audio routes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) * @num: number of routes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) * Removes routes from the DAPM context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) const struct snd_soc_dapm_route *route, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) snd_soc_dapm_del_route(dapm, route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) route++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) EXPORT_SYMBOL_GPL(snd_soc_dapm_del_routes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) const struct snd_soc_dapm_route *route)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) struct snd_soc_dapm_widget *source = dapm_find_widget(dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) route->source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) struct snd_soc_dapm_widget *sink = dapm_find_widget(dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) route->sink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) if (!source) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) dev_err(dapm->dev, "ASoC: Unable to find source %s for weak route\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) route->source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) if (!sink) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) dev_err(dapm->dev, "ASoC: Unable to find sink %s for weak route\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) route->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) if (route->control || route->connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) dev_warn(dapm->dev, "ASoC: Ignoring control for weak route %s->%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) route->source, route->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) snd_soc_dapm_widget_for_each_sink_path(source, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) if (path->sink == sink) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) path->weak = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) dev_err(dapm->dev, "ASoC: No path found for weak route %s->%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) route->source, route->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) if (count > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) dev_warn(dapm->dev, "ASoC: %d paths found for weak route %s->%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) count, route->source, route->sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) * snd_soc_dapm_weak_routes - Mark routes between DAPM widgets as weak
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) * @route: audio routes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) * @num: number of routes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) * Mark existing routes matching those specified in the passed array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) * as being weak, meaning that they are ignored for the purpose of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) * power decisions. The main intended use case is for sidetone paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) * which couple audio between other independent paths if they are both
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) * active in order to make the combination work better at the user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) * level but which aren't intended to be "used".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) * Note that CODEC drivers should not use this as sidetone type paths
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) * can frequently also be used as bypass paths.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) const struct snd_soc_dapm_route *route, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) err = snd_soc_dapm_weak_route(dapm, route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) ret = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) route++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) * snd_soc_dapm_new_widgets - add new dapm widgets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) * @card: card to be checked for new dapm widgets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) * Checks the codec for any new dapm widgets and creates them if found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) * Returns 0 for success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) for_each_card_widgets(card, w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) if (w->new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) if (w->num_kcontrols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) w->kcontrols = kcalloc(w->num_kcontrols,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) sizeof(struct snd_kcontrol *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) if (!w->kcontrols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) switch(w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) case snd_soc_dapm_switch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) case snd_soc_dapm_mixer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) case snd_soc_dapm_mixer_named_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) dapm_new_mixer(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) case snd_soc_dapm_mux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) case snd_soc_dapm_demux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) dapm_new_mux(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) case snd_soc_dapm_pga:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) case snd_soc_dapm_effect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) case snd_soc_dapm_out_drv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) dapm_new_pga(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) case snd_soc_dapm_dai_link:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) dapm_new_dai_link(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) /* Read the initial power state from the device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) if (w->reg >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) val = soc_dapm_read(w->dapm, w->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) val = val >> w->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) val &= w->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) if (val == w->on_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) w->power = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) w->new = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) dapm_mark_dirty(w, "new widget");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) dapm_debugfs_add_widget(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) dapm_power_widgets(card, SND_SOC_DAPM_STREAM_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) * snd_soc_dapm_get_volsw - dapm mixer get callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) * @kcontrol: mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) * @ucontrol: control element information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) * Callback to get the value of a dapm mixer control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) * Returns 0 for success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) struct soc_mixer_control *mc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) (struct soc_mixer_control *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) int reg = mc->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) unsigned int shift = mc->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) int max = mc->max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) unsigned int width = fls(max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) unsigned int mask = (1 << fls(max)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) unsigned int invert = mc->invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) unsigned int reg_val, val, rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) reg_val = soc_dapm_read(dapm, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) val = (reg_val >> shift) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) if (reg != mc->rreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) reg_val = soc_dapm_read(dapm, mc->rreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) if (snd_soc_volsw_is_stereo(mc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) rval = (reg_val >> mc->rshift) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) reg_val = dapm_kcontrol_get_value(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) val = reg_val & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) if (snd_soc_volsw_is_stereo(mc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) rval = (reg_val >> width) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) ucontrol->value.integer.value[0] = max - val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) ucontrol->value.integer.value[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) if (snd_soc_volsw_is_stereo(mc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) ucontrol->value.integer.value[1] = max - rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) ucontrol->value.integer.value[1] = rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) * snd_soc_dapm_put_volsw - dapm mixer set callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) * @kcontrol: mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) * @ucontrol: control element information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) * Callback to set the value of a dapm mixer control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) * Returns 0 for success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) struct soc_mixer_control *mc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) (struct soc_mixer_control *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) int reg = mc->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) unsigned int shift = mc->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) int max = mc->max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) unsigned int width = fls(max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) unsigned int mask = (1 << width) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) unsigned int invert = mc->invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) unsigned int val, rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) int connect, rconnect = -1, change, reg_change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) struct snd_soc_dapm_update update = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) val = (ucontrol->value.integer.value[0] & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) connect = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) val = max - val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) if (snd_soc_volsw_is_stereo(mc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) rval = (ucontrol->value.integer.value[1] & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) rconnect = !!rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) rval = max - rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) /* This assumes field width < (bits in unsigned int / 2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) if (width > sizeof(unsigned int) * 8 / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) dev_warn(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) "ASoC: control %s field width limit exceeded\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) kcontrol->id.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) change = dapm_kcontrol_set_value(kcontrol, val | (rval << width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) if (reg != SND_SOC_NOPM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) val = val << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) rval = rval << mc->rshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) reg_change = soc_dapm_test_bits(dapm, reg, mask << shift, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) if (snd_soc_volsw_is_stereo(mc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) reg_change |= soc_dapm_test_bits(dapm, mc->rreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) mask << mc->rshift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) if (change || reg_change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) if (reg_change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) if (snd_soc_volsw_is_stereo(mc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) update.has_second_set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) update.reg2 = mc->rreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) update.mask2 = mask << mc->rshift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) update.val2 = rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) update.kcontrol = kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) update.reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) update.mask = mask << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) update.val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) card->update = &update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) change |= reg_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) ret = soc_dapm_mixer_update_power(card, kcontrol, connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) rconnect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) card->update = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) snd_soc_dpcm_runtime_update(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) * @kcontrol: mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) * @ucontrol: control element information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) * Callback to get the value of a dapm enumerated double mixer control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) * Returns 0 for success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) unsigned int reg_val, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) if (e->reg != SND_SOC_NOPM && dapm_kcontrol_is_powered(kcontrol)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) reg_val = soc_dapm_read(dapm, e->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) reg_val = dapm_kcontrol_get_value(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) val = (reg_val >> e->shift_l) & e->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) ucontrol->value.enumerated.item[0] = snd_soc_enum_val_to_item(e, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) if (e->shift_l != e->shift_r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) val = (reg_val >> e->shift_r) & e->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) val = snd_soc_enum_val_to_item(e, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) ucontrol->value.enumerated.item[1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) * @kcontrol: mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) * @ucontrol: control element information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) * Callback to set the value of a dapm enumerated double mixer control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) * Returns 0 for success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) unsigned int *item = ucontrol->value.enumerated.item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) unsigned int val, change, reg_change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) struct snd_soc_dapm_update update = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) if (item[0] >= e->items)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) mask = e->mask << e->shift_l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) if (e->shift_l != e->shift_r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) if (item[1] > e->items)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) mask |= e->mask << e->shift_r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) change = dapm_kcontrol_set_value(kcontrol, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) if (e->reg != SND_SOC_NOPM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) reg_change = soc_dapm_test_bits(dapm, e->reg, mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) if (change || reg_change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) if (reg_change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) update.kcontrol = kcontrol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) update.reg = e->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) update.mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) update.val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) card->update = &update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) change |= reg_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) ret = soc_dapm_mux_update_power(card, kcontrol, item[0], e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) card->update = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) snd_soc_dpcm_runtime_update(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) * snd_soc_dapm_info_pin_switch - Info for a pin switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) * @kcontrol: mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) * @uinfo: control element information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) * Callback to provide information about a pin switch control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) uinfo->value.integer.max = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) * snd_soc_dapm_get_pin_switch - Get information for a pin switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) * @kcontrol: mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) * @ucontrol: Value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) const char *pin = (const char *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) ucontrol->value.integer.value[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) snd_soc_dapm_get_pin_status(&card->dapm, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) * snd_soc_dapm_put_pin_switch - Set information for a pin switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) * @kcontrol: mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) * @ucontrol: Value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) const char *pin = (const char *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) ret = __snd_soc_dapm_set_pin(&card->dapm, pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) !!ucontrol->value.integer.value[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) snd_soc_dapm_sync(&card->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) struct snd_soc_dapm_widget *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) const struct snd_soc_dapm_widget *widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) enum snd_soc_dapm_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) const char *prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) if ((w = dapm_cnew_widget(widget)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) case snd_soc_dapm_regulator_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) w->regulator = devm_regulator_get(dapm->dev, w->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) if (IS_ERR(w->regulator)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) ret = PTR_ERR(w->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) goto request_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) ret = regulator_allow_bypass(w->regulator, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) dev_warn(dapm->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) "ASoC: Failed to bypass %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) case snd_soc_dapm_pinctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) w->pinctrl = devm_pinctrl_get(dapm->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) if (IS_ERR(w->pinctrl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) ret = PTR_ERR(w->pinctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) goto request_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) /* set to sleep_state when initializing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) dapm_pinctrl_event(w, NULL, SND_SOC_DAPM_POST_PMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) case snd_soc_dapm_clock_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) w->clk = devm_clk_get(dapm->dev, w->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) if (IS_ERR(w->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) ret = PTR_ERR(w->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) goto request_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) prefix = soc_dapm_prefix(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) if (prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) w->name = kstrdup_const(widget->name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) if (w->name == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) kfree_const(w->sname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) kfree(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) case snd_soc_dapm_mic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) w->is_ep = SND_SOC_DAPM_EP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) w->power_check = dapm_generic_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) case snd_soc_dapm_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) if (!dapm->card->fully_routed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) w->is_ep = SND_SOC_DAPM_EP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) w->power_check = dapm_generic_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) case snd_soc_dapm_spk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) case snd_soc_dapm_hp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) w->is_ep = SND_SOC_DAPM_EP_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) w->power_check = dapm_generic_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) case snd_soc_dapm_output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) if (!dapm->card->fully_routed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) w->is_ep = SND_SOC_DAPM_EP_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) w->power_check = dapm_generic_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) case snd_soc_dapm_vmid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) case snd_soc_dapm_siggen:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) w->is_ep = SND_SOC_DAPM_EP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) w->power_check = dapm_always_on_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) case snd_soc_dapm_sink:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) w->is_ep = SND_SOC_DAPM_EP_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) w->power_check = dapm_always_on_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) case snd_soc_dapm_mux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) case snd_soc_dapm_demux:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) case snd_soc_dapm_switch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) case snd_soc_dapm_mixer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) case snd_soc_dapm_mixer_named_ctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) case snd_soc_dapm_adc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) case snd_soc_dapm_aif_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) case snd_soc_dapm_dac:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) case snd_soc_dapm_aif_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) case snd_soc_dapm_pga:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) case snd_soc_dapm_buffer:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) case snd_soc_dapm_scheduler:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) case snd_soc_dapm_effect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) case snd_soc_dapm_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) case snd_soc_dapm_asrc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) case snd_soc_dapm_encoder:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) case snd_soc_dapm_decoder:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) case snd_soc_dapm_out_drv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) case snd_soc_dapm_micbias:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) case snd_soc_dapm_line:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) case snd_soc_dapm_dai_link:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) case snd_soc_dapm_dai_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) case snd_soc_dapm_dai_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) w->power_check = dapm_generic_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) case snd_soc_dapm_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) case snd_soc_dapm_regulator_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) case snd_soc_dapm_pinctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) case snd_soc_dapm_clock_supply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) case snd_soc_dapm_kcontrol:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) w->is_supply = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) w->power_check = dapm_supply_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) w->power_check = dapm_always_on_check_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) w->dapm = dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) INIT_LIST_HEAD(&w->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) INIT_LIST_HEAD(&w->dirty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) /* see for_each_card_widgets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) list_add_tail(&w->list, &dapm->card->widgets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) snd_soc_dapm_for_each_direction(dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) INIT_LIST_HEAD(&w->edges[dir]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) w->endpoints[dir] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) /* machine layer sets up unconnected pins and insertions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) w->connected = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) return w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) request_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) dev_err(dapm->dev, "ASoC: Failed to request %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) w->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) kfree_const(w->sname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) kfree(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) * snd_soc_dapm_new_control - create new dapm control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) * @widget: widget template
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) * Creates new DAPM control based upon a template.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) * Returns a widget pointer on success or an error pointer on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) struct snd_soc_dapm_widget *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) const struct snd_soc_dapm_widget *widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) w = snd_soc_dapm_new_control_unlocked(dapm, widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) return w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) * snd_soc_dapm_new_controls - create new dapm controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) * @widget: widget array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) * @num: number of widgets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) * Creates new DAPM controls based upon the templates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) * Returns 0 for success else error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) const struct snd_soc_dapm_widget *widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) w = snd_soc_dapm_new_control_unlocked(dapm, widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) if (IS_ERR(w)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) ret = PTR_ERR(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) widget++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) struct snd_soc_dai *source, *sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) struct snd_pcm_hw_params *params = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) const struct snd_soc_pcm_stream *config = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) struct snd_pcm_runtime *runtime = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) unsigned int fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) params = kzalloc(sizeof(*params), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) if (!params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) if (!runtime) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) substream->runtime = runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) substream->stream = SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) snd_soc_dapm_widget_for_each_source_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) source = path->source->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) ret = snd_soc_dai_startup(source, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) dev_err(source->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) "ASoC: startup() failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) snd_soc_dai_activate(source, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) substream->stream = SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) snd_soc_dapm_widget_for_each_sink_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) sink = path->sink->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) ret = snd_soc_dai_startup(sink, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) dev_err(sink->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) "ASoC: startup() failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) snd_soc_dai_activate(sink, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) substream->hw_opened = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) * Note: getting the config after .startup() gives a chance to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) * either party on the link to alter the configuration if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) * necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) config = rtd->dai_link->params + rtd->params_select;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) if (WARN_ON(!config)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) dev_err(w->dapm->dev, "ASoC: link config missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) /* Be a little careful as we don't want to overflow the mask array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) if (config->formats) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) fmt = ffs(config->formats) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) dev_warn(w->dapm->dev, "ASoC: Invalid format %llx specified\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) config->formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) snd_mask_set(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) config->rate_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE)->max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) config->rate_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->min
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) = config->channels_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) = config->channels_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) substream->stream = SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) snd_soc_dapm_widget_for_each_source_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) source = path->source->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) ret = snd_soc_dai_hw_params(source, substream, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) dapm_update_dai_unlocked(substream, params, source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) substream->stream = SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) snd_soc_dapm_widget_for_each_sink_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) sink = path->sink->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) ret = snd_soc_dai_hw_params(sink, substream, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) dapm_update_dai_unlocked(substream, params, sink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) runtime->format = params_format(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) runtime->subformat = params_subformat(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) runtime->channels = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) runtime->rate = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) kfree(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) struct snd_kcontrol *kcontrol, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) struct snd_soc_dapm_path *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) struct snd_soc_dai *source, *sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) struct snd_pcm_substream *substream = w->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) int ret = 0, saved_stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) if (WARN_ON(list_empty(&w->edges[SND_SOC_DAPM_DIR_OUT]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) list_empty(&w->edges[SND_SOC_DAPM_DIR_IN])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) case SND_SOC_DAPM_PRE_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) ret = snd_soc_dai_link_event_pre_pmu(w, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) case SND_SOC_DAPM_POST_PMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) snd_soc_dapm_widget_for_each_sink_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) sink = path->sink->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) ret = snd_soc_dai_digital_mute(sink, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) SNDRV_PCM_STREAM_PLAYBACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) if (ret != 0 && ret != -ENOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) dev_warn(sink->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) "ASoC: Failed to unmute: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) case SND_SOC_DAPM_PRE_PMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) snd_soc_dapm_widget_for_each_sink_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) sink = path->sink->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) ret = snd_soc_dai_digital_mute(sink, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) SNDRV_PCM_STREAM_PLAYBACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) if (ret != 0 && ret != -ENOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) dev_warn(sink->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) "ASoC: Failed to mute: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) substream->stream = SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) snd_soc_dapm_widget_for_each_source_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) source = path->source->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) snd_soc_dai_hw_free(source, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) substream->stream = SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) snd_soc_dapm_widget_for_each_sink_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) sink = path->sink->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) snd_soc_dai_hw_free(sink, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) substream->stream = SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) snd_soc_dapm_widget_for_each_source_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) source = path->source->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) snd_soc_dai_deactivate(source, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) snd_soc_dai_shutdown(source, substream, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) substream->stream = SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) snd_soc_dapm_widget_for_each_sink_path(w, path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) sink = path->sink->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) snd_soc_dai_deactivate(sink, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) snd_soc_dai_shutdown(sink, substream, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) case SND_SOC_DAPM_POST_PMD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) kfree(substream->runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) WARN(1, "Unknown event %d\n", event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) /* Restore the substream direction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) substream->stream = saved_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) static int snd_soc_dapm_dai_link_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) struct snd_soc_pcm_runtime *rtd = w->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) ucontrol->value.enumerated.item[0] = rtd->params_select;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) struct snd_soc_pcm_runtime *rtd = w->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) /* Can't change the config when widget is already powered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) if (w->power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) if (ucontrol->value.enumerated.item[0] == rtd->params_select)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) if (ucontrol->value.enumerated.item[0] >= rtd->dai_link->num_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) rtd->params_select = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) snd_soc_dapm_free_kcontrol(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) unsigned long *private_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) int num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) const char **w_param_text)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) devm_kfree(card->dev, (void *)*private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) if (!w_param_text)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) for (count = 0 ; count < num_params; count++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) devm_kfree(card->dev, (void *)w_param_text[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) devm_kfree(card->dev, w_param_text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) static struct snd_kcontrol_new *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) char *link_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) const struct snd_soc_pcm_stream *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) int num_params, const char **w_param_text,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) unsigned long *private_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) struct soc_enum w_param_enum[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) SOC_ENUM_SINGLE(0, 0, 0, NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) struct snd_kcontrol_new kcontrol_dai_link[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) SOC_ENUM_EXT(NULL, w_param_enum[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) snd_soc_dapm_dai_link_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) snd_soc_dapm_dai_link_put),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) struct snd_kcontrol_new *kcontrol_news;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) const struct snd_soc_pcm_stream *config = params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) for (count = 0 ; count < num_params; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) if (!config->stream_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) dev_warn(card->dapm.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) "ASoC: anonymous config %d for dai link %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) count, link_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) w_param_text[count] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) devm_kasprintf(card->dev, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) "Anonymous Configuration %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) w_param_text[count] = devm_kmemdup(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) config->stream_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) strlen(config->stream_name) + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) if (!w_param_text[count])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) goto outfree_w_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) config++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) w_param_enum[0].items = num_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) w_param_enum[0].texts = w_param_text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) *private_value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) (unsigned long) devm_kmemdup(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) (void *)(kcontrol_dai_link[0].private_value),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) sizeof(struct soc_enum), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) if (!*private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) dev_err(card->dev, "ASoC: Failed to create control for %s widget\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) link_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) goto outfree_w_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) kcontrol_dai_link[0].private_value = *private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) /* duplicate kcontrol_dai_link on heap so that memory persists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) kcontrol_news = devm_kmemdup(card->dev, &kcontrol_dai_link[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) sizeof(struct snd_kcontrol_new),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) if (!kcontrol_news) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) dev_err(card->dev, "ASoC: Failed to create control for %s widget\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) link_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) goto outfree_w_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) return kcontrol_news;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) outfree_w_param:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) snd_soc_dapm_free_kcontrol(card, private_value, num_params, w_param_text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) static struct snd_soc_dapm_widget *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) snd_soc_dapm_new_dai(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) char *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) struct snd_soc_dapm_widget template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) const char **w_param_text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) unsigned long private_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) char *link_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) link_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s-%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) rtd->dai_link->name, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) if (!link_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) memset(&template, 0, sizeof(template));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) template.reg = SND_SOC_NOPM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) template.id = snd_soc_dapm_dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) template.name = link_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) template.event = snd_soc_dai_link_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) template.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) template.kcontrol_news = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) /* allocate memory for control, only in case of multiple configs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) if (rtd->dai_link->num_params > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) w_param_text = devm_kcalloc(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) rtd->dai_link->num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) sizeof(char *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179) if (!w_param_text) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) goto param_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) template.num_kcontrols = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) template.kcontrol_news =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) snd_soc_dapm_alloc_kcontrol(card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) link_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) rtd->dai_link->params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) rtd->dai_link->num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) w_param_text, &private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) if (!template.kcontrol_news) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) goto param_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196) w_param_text = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) dev_dbg(card->dev, "ASoC: adding %s widget\n", link_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) if (IS_ERR(w)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) ret = PTR_ERR(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) dev_err(rtd->dev, "ASoC: Failed to create %s widget: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) link_name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) goto outfree_kcontrol_news;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) w->priv = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) return w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) outfree_kcontrol_news:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) devm_kfree(card->dev, (void *)template.kcontrol_news);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) snd_soc_dapm_free_kcontrol(card, &private_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) rtd->dai_link->num_params, w_param_text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) param_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) devm_kfree(card->dev, link_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) struct snd_soc_dapm_widget template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) WARN_ON(dapm->dev != dai->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) memset(&template, 0, sizeof(template));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) template.reg = SND_SOC_NOPM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232) if (dai->driver->playback.stream_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) template.id = snd_soc_dapm_dai_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) template.name = dai->driver->playback.stream_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) template.sname = dai->driver->playback.stream_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) dev_dbg(dai->dev, "ASoC: adding %s widget\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) template.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240) w = snd_soc_dapm_new_control_unlocked(dapm, &template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) if (IS_ERR(w))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) return PTR_ERR(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) w->priv = dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) dai->playback_widget = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) if (dai->driver->capture.stream_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) template.id = snd_soc_dapm_dai_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) template.name = dai->driver->capture.stream_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) template.sname = dai->driver->capture.stream_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) dev_dbg(dai->dev, "ASoC: adding %s widget\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) template.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) w = snd_soc_dapm_new_control_unlocked(dapm, &template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) if (IS_ERR(w))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) return PTR_ERR(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) w->priv = dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) dai->capture_widget = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) struct snd_soc_dapm_widget *dai_w, *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270) struct snd_soc_dapm_widget *src, *sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) /* For each DAI widget... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) for_each_card_widgets(card, dai_w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) switch (dai_w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) case snd_soc_dapm_dai_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) case snd_soc_dapm_dai_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) /* let users know there is no DAI to link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) if (!dai_w->priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) dev_dbg(card->dev, "dai widget %s has no DAI\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) dai_w->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) dai = dai_w->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292) /* ...find all widgets with the same stream and link them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) for_each_card_widgets(card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) if (w->dapm != dai_w->dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) switch (w->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) case snd_soc_dapm_dai_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) case snd_soc_dapm_dai_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305) if (!w->sname || !strstr(w->sname, dai_w->sname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308) if (dai_w->id == snd_soc_dapm_dai_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) src = dai_w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) sink = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) src = w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) sink = dai_w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315) dev_dbg(dai->dev, "%s -> %s\n", src->name, sink->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) snd_soc_dapm_add_path(w->dapm, src, sink, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323) static void dapm_connect_dai_routes(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324) struct snd_soc_dai *src_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325) struct snd_soc_dapm_widget *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) struct snd_soc_dapm_widget *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327) struct snd_soc_dai *sink_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) struct snd_soc_dapm_widget *sink)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330) dev_dbg(dapm->dev, "connected DAI link %s:%s -> %s:%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331) src_dai->component->name, src->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) sink_dai->component->name, sink->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334) if (dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335) snd_soc_dapm_add_path(dapm, src, dai, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) src = dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339) snd_soc_dapm_add_path(dapm, src, sink, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) static void dapm_connect_dai_pair(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343) struct snd_soc_pcm_runtime *rtd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) struct snd_soc_dai *codec_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345) struct snd_soc_dai *cpu_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) struct snd_soc_dai_link *dai_link = rtd->dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) struct snd_soc_dapm_widget *dai, *codec, *playback_cpu, *capture_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350) struct snd_pcm_str *streams = rtd->pcm->streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352) if (dai_link->params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353) playback_cpu = cpu_dai->capture_widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) capture_cpu = cpu_dai->playback_widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356) playback_cpu = cpu_dai->playback_widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357) capture_cpu = cpu_dai->capture_widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360) /* connect BE DAI playback if widgets are valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) codec = codec_dai->playback_widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363) if (playback_cpu && codec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364) if (dai_link->params && !rtd->playback_widget) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365) substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) dai = snd_soc_dapm_new_dai(card, substream, "playback");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367) if (IS_ERR(dai))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) goto capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369) rtd->playback_widget = dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372) dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373) rtd->playback_widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374) codec_dai, codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) capture:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378) /* connect BE DAI capture if widgets are valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379) codec = codec_dai->capture_widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381) if (codec && capture_cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382) if (dai_link->params && !rtd->capture_widget) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383) substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384) dai = snd_soc_dapm_new_dai(card, substream, "capture");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) if (IS_ERR(dai))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387) rtd->capture_widget = dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) dapm_connect_dai_routes(&card->dapm, codec_dai, codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391) rtd->capture_widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392) cpu_dai, capture_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396) static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400) unsigned int ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402) w = snd_soc_dai_get_widget(dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404) if (w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405) dapm_mark_dirty(w, "stream event");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407) if (w->id == snd_soc_dapm_dai_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408) ep = SND_SOC_DAPM_EP_SOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) dapm_widget_invalidate_input_paths(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411) ep = SND_SOC_DAPM_EP_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412) dapm_widget_invalidate_output_paths(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) case SND_SOC_DAPM_STREAM_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417) w->active = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) w->is_ep = ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) case SND_SOC_DAPM_STREAM_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) w->active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422) w->is_ep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) case SND_SOC_DAPM_STREAM_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425) case SND_SOC_DAPM_STREAM_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426) case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433) void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) struct snd_soc_pcm_runtime *rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) struct snd_soc_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) /* for each BE DAI link... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440) for_each_card_rtds(card, rtd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442) * dynamic FE links have no fixed DAI mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443) * CODEC<->CODEC links have no direct connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445) if (rtd->dai_link->dynamic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) if (rtd->num_cpus == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449) for_each_rtd_codec_dais(rtd, i, codec_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450) dapm_connect_dai_pair(card, rtd, codec_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451) asoc_rtd_to_cpu(rtd, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452) } else if (rtd->num_codecs == rtd->num_cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453) for_each_rtd_codec_dais(rtd, i, codec_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454) dapm_connect_dai_pair(card, rtd, codec_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) asoc_rtd_to_cpu(rtd, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) dev_err(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458) "N cpus to M codecs link is not supported yet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463) static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464) int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469) for_each_rtd_dais(rtd, i, dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470) soc_dapm_dai_stream_event(dai, stream, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) dapm_power_widgets(rtd->card, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476) * snd_soc_dapm_stream_event - send a stream event to the dapm core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477) * @rtd: PCM runtime data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478) * @stream: stream name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479) * @event: stream event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481) * Sends a stream event to the dapm core. The core then makes any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) * necessary widget power changes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484) * Returns 0 for success else error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487) int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489) struct snd_soc_card *card = rtd->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491) mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492) soc_dapm_stream_event(rtd, stream, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496) void snd_soc_dapm_stream_stop(struct snd_soc_pcm_runtime *rtd, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499) if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) /* powered down playback stream now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501) snd_soc_dapm_stream_event(rtd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502) SNDRV_PCM_STREAM_PLAYBACK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503) SND_SOC_DAPM_STREAM_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505) /* start delayed pop wq here for playback streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506) rtd->pop_wait = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) queue_delayed_work(system_power_efficient_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508) &rtd->delayed_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) msecs_to_jiffies(rtd->pmdown_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) /* capture streams can be powered down now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514) SND_SOC_DAPM_STREAM_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517) EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520) * snd_soc_dapm_enable_pin_unlocked - enable pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522) * @pin: pin name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) * Enables input/output pin and its parents or children widgets iff there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4525) * a valid audio route and active audio stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4526) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4527) * Requires external locking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4528) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4529) * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4530) * do any widget power switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4531) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4532) int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4533) const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4535) return snd_soc_dapm_set_pin(dapm, pin, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4537) EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin_unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4539) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4540) * snd_soc_dapm_enable_pin - enable pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4541) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4542) * @pin: pin name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4543) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4544) * Enables input/output pin and its parents or children widgets iff there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4545) * a valid audio route and active audio stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4546) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4547) * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4548) * do any widget power switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4550) int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4552) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4554) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4556) ret = snd_soc_dapm_set_pin(dapm, pin, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4558) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4560) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4562) EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4564) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4565) * snd_soc_dapm_force_enable_pin_unlocked - force a pin to be enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4566) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4567) * @pin: pin name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4568) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4569) * Enables input/output pin regardless of any other state. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4570) * intended for use with microphone bias supplies used in microphone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4571) * jack detection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4572) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4573) * Requires external locking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4574) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4575) * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4576) * do any widget power switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4577) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4578) int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4579) const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4581) struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4583) if (!w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4584) dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4585) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4588) dev_dbg(w->dapm->dev, "ASoC: force enable pin %s\n", pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4589) if (!w->connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4590) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4591) * w->force does not affect the number of input or output paths,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4592) * so we only have to recheck if w->connected is changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4593) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4594) dapm_widget_invalidate_input_paths(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4595) dapm_widget_invalidate_output_paths(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4596) w->connected = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4598) w->force = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4599) dapm_mark_dirty(w, "force enable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4601) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4603) EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin_unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4605) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4606) * snd_soc_dapm_force_enable_pin - force a pin to be enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4607) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4608) * @pin: pin name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4609) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4610) * Enables input/output pin regardless of any other state. This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4611) * intended for use with microphone bias supplies used in microphone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4612) * jack detection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4613) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4614) * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4615) * do any widget power switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4617) int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4618) const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4620) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4622) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4624) ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4626) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4628) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4630) EXPORT_SYMBOL_GPL(snd_soc_dapm_force_enable_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4632) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4633) * snd_soc_dapm_disable_pin_unlocked - disable pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4634) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4635) * @pin: pin name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4636) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4637) * Disables input/output pin and its parents or children widgets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4638) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4639) * Requires external locking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4640) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4641) * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4642) * do any widget power switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4643) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4644) int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4645) const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4647) return snd_soc_dapm_set_pin(dapm, pin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4649) EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin_unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4651) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4652) * snd_soc_dapm_disable_pin - disable pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4653) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4654) * @pin: pin name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4655) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4656) * Disables input/output pin and its parents or children widgets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4657) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4658) * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4659) * do any widget power switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4660) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4661) int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4662) const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4664) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4666) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4668) ret = snd_soc_dapm_set_pin(dapm, pin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4670) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4672) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4674) EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4676) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4677) * snd_soc_dapm_nc_pin_unlocked - permanently disable pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4678) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4679) * @pin: pin name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4680) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4681) * Marks the specified pin as being not connected, disabling it along
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4682) * any parent or child widgets. At present this is identical to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4683) * snd_soc_dapm_disable_pin() but in future it will be extended to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4684) * additional things such as disabling controls which only affect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4685) * paths through the pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4686) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4687) * Requires external locking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4688) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4689) * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4690) * do any widget power switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4692) int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4693) const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4695) return snd_soc_dapm_set_pin(dapm, pin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4697) EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin_unlocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4699) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4700) * snd_soc_dapm_nc_pin - permanently disable pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4701) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4702) * @pin: pin name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4703) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4704) * Marks the specified pin as being not connected, disabling it along
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4705) * any parent or child widgets. At present this is identical to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4706) * snd_soc_dapm_disable_pin() but in future it will be extended to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4707) * additional things such as disabling controls which only affect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4708) * paths through the pin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4709) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4710) * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4711) * do any widget power switching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4713) int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4715) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4717) mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4719) ret = snd_soc_dapm_set_pin(dapm, pin, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4721) mutex_unlock(&dapm->card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4723) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4725) EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4727) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4728) * snd_soc_dapm_get_pin_status - get audio pin status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4729) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4730) * @pin: audio signal pin endpoint (or start point)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4731) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4732) * Get audio pin status - connected or disconnected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4733) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4734) * Returns 1 for connected otherwise 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4735) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4736) int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4737) const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4739) struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4741) if (w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4742) return w->connected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4744) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4746) EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4748) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4749) * snd_soc_dapm_ignore_suspend - ignore suspend status for DAPM endpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4750) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4751) * @pin: audio signal pin endpoint (or start point)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4752) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4753) * Mark the given endpoint or pin as ignoring suspend. When the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4754) * system is disabled a path between two endpoints flagged as ignoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4755) * suspend will not be disabled. The path must already be enabled via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4756) * normal means at suspend time, it will not be turned on if it was not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4757) * already enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4759) int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4760) const char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4762) struct snd_soc_dapm_widget *w = dapm_find_widget(dapm, pin, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4764) if (!w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4765) dev_err(dapm->dev, "ASoC: unknown pin %s\n", pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4766) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4769) w->ignore_suspend = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4771) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4773) EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4775) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4776) * snd_soc_dapm_free - free dapm resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4777) * @dapm: DAPM context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4778) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4779) * Free all dapm widgets and resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4780) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4781) void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4783) dapm_debugfs_cleanup(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4784) dapm_free_widgets(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4785) list_del(&dapm->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4787) EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4789) void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4790) struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4791) struct snd_soc_component *component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4793) dapm->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4794) dapm->component = component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4795) dapm->bias_level = SND_SOC_BIAS_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4797) if (component) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4798) dapm->dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4799) dapm->idle_bias_off = !component->driver->idle_bias_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4800) dapm->suspend_bias_off = component->driver->suspend_bias_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4801) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4802) dapm->dev = card->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4805) INIT_LIST_HEAD(&dapm->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4806) /* see for_each_card_dapms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4807) list_add(&dapm->list, &card->dapm_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4809) EXPORT_SYMBOL_GPL(snd_soc_dapm_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4811) static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4813) struct snd_soc_card *card = dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4814) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4815) LIST_HEAD(down_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4816) int powerdown = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4818) mutex_lock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4820) for_each_card_widgets(dapm->card, w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4821) if (w->dapm != dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4822) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4823) if (w->power) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4824) dapm_seq_insert(w, &down_list, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4825) w->new_power = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4826) powerdown = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4830) /* If there were no widgets to power down we're already in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4831) * standby.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4832) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4833) if (powerdown) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4834) if (dapm->bias_level == SND_SOC_BIAS_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4835) snd_soc_dapm_set_bias_level(dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4836) SND_SOC_BIAS_PREPARE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4837) dapm_seq_run(card, &down_list, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4838) if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4839) snd_soc_dapm_set_bias_level(dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4840) SND_SOC_BIAS_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4843) mutex_unlock(&card->dapm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4846) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4847) * snd_soc_dapm_shutdown - callback for system shutdown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4849) void snd_soc_dapm_shutdown(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4851) struct snd_soc_dapm_context *dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4853) for_each_card_dapms(card, dapm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4854) if (dapm != &card->dapm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4855) soc_dapm_shutdown_dapm(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4856) if (dapm->bias_level == SND_SOC_BIAS_STANDBY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4857) snd_soc_dapm_set_bias_level(dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4858) SND_SOC_BIAS_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4862) soc_dapm_shutdown_dapm(&card->dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4863) if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4864) snd_soc_dapm_set_bias_level(&card->dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4865) SND_SOC_BIAS_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4868) /* Module information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4869) MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4870) MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4871) MODULE_LICENSE("GPL");