Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");