^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-pcm.c -- ALSA SoC PCM
^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) // Copyright 2005 Openedhand Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // Copyright (C) 2010 Slimlogic Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // Copyright (C) 2010 Texas Instruments Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // Authors: Liam Girdwood <lrg@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // Mark Brown <broonie@opensource.wolfsonmicro.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pinctrl/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <sound/soc-dpcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <sound/soc-link.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <trace/hooks/sound.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DPCM_MAX_BE_USERS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static const char *dpcm_state_string(enum snd_soc_dpcm_state state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) case SND_SOC_DPCM_STATE_NEW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return "new";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) case SND_SOC_DPCM_STATE_OPEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return "open";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) case SND_SOC_DPCM_STATE_HW_PARAMS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return "hw_params";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) case SND_SOC_DPCM_STATE_PREPARE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return "prepare";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case SND_SOC_DPCM_STATE_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return "start";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case SND_SOC_DPCM_STATE_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return "stop";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case SND_SOC_DPCM_STATE_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return "suspend";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case SND_SOC_DPCM_STATE_PAUSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return "paused";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case SND_SOC_DPCM_STATE_HW_FREE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return "hw_free";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case SND_SOC_DPCM_STATE_CLOSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return "close";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int stream, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ssize_t offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* FE state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) offset += scnprintf(buf + offset, size - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) "[%s - %s]\n", fe->dai_link->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) stream ? "Capture" : "Playback");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) offset += scnprintf(buf + offset, size - offset, "State: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) dpcm_state_string(fe->dpcm[stream].state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) offset += scnprintf(buf + offset, size - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) "Hardware Params: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "Format = %s, Channels = %d, Rate = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) snd_pcm_format_name(params_format(params)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) params_channels(params),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* BEs state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) offset += scnprintf(buf + offset, size - offset, "Backends:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (list_empty(&fe->dpcm[stream].be_clients)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) offset += scnprintf(buf + offset, size - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) " No active DSP links\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) spin_lock_irqsave(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) params = &dpcm->hw_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) offset += scnprintf(buf + offset, size - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) "- %s\n", be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) offset += scnprintf(buf + offset, size - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) " State: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) dpcm_state_string(be->dpcm[stream].state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) offset += scnprintf(buf + offset, size - offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) " Hardware Params: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) "Format = %s, Channels = %d, Rate = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) snd_pcm_format_name(params_format(params)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) params_channels(params),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) params_rate(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static ssize_t dpcm_state_read_file(struct file *file, char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct snd_soc_pcm_runtime *fe = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ssize_t out_count = PAGE_SIZE, offset = 0, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (fe->num_cpus > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) dev_err(fe->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "%s doesn't support Multi CPU yet\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) buf = kmalloc(out_count, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) for_each_pcm_streams(stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) offset += dpcm_show_state(fe, stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) buf + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) out_count - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ret = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static const struct file_operations dpcm_state_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .open = simple_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .read = dpcm_state_read_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (!rtd->dai_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (!rtd->dai_link->dynamic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (!rtd->card->debugfs_card_root)
^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) rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) rtd->card->debugfs_card_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) debugfs_create_file("state", 0444, rtd->debugfs_dpcm_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) rtd, &dpcm_state_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) name = kasprintf(GFP_KERNEL, "%s:%s", dpcm->be->dai_link->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) stream ? "capture" : "playback");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) dpcm->debugfs_state = debugfs_create_dir(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) name, dpcm->fe->debugfs_dpcm_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) debugfs_create_u32("state", 0644, dpcm->debugfs_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) &dpcm->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) kfree(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) debugfs_remove_recursive(dpcm->debugfs_state);
^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) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static inline void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static inline void dpcm_remove_debugfs_state(struct snd_soc_dpcm *dpcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * snd_soc_runtime_action() - Increment/Decrement active count for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * PCM runtime components
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @rtd: ASoC PCM runtime that is activated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * @stream: Direction of the PCM stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * @action: Activate stream if 1. Deactivate if -1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Increments/Decrements the active count for all the DAIs and components
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * attached to a PCM runtime.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * Should typically be called when a stream is opened.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Must be called with the rtd->card->pcm_mutex being held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int stream, int action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) lockdep_assert_held(&rtd->card->pcm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) for_each_rtd_dais(rtd, i, dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) snd_soc_dai_action(dai, stream, action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) EXPORT_SYMBOL_GPL(snd_soc_runtime_action);
^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) * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * @rtd: The ASoC PCM runtime that should be checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * This function checks whether the power down delay should be ignored for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * specific PCM runtime. Returns true if the delay is 0, if it the DAI link has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * been configured to ignore the delay, or if none of the components benefits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * from having the delay.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) bool ignore = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) for_each_rtd_components(rtd, i, component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ignore &= !component->driver->use_pmdown_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return ignore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * @substream: the pcm substream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * @hw: the hardware parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * Sets the substream runtime hardware parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) const struct snd_pcm_hardware *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) runtime->hw.info = hw->info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) runtime->hw.formats = hw->formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) runtime->hw.period_bytes_min = hw->period_bytes_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) runtime->hw.period_bytes_max = hw->period_bytes_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) runtime->hw.periods_min = hw->periods_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) runtime->hw.periods_max = hw->periods_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) runtime->hw.fifo_size = hw->fifo_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* DPCM stream event, send event to FE and all active BEs. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) for_each_dpcm_be(fe, dir, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dev_dbg(be->dev, "ASoC: BE %s event %d dir %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) be->dai_link->name, event, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if ((event == SND_SOC_DAPM_STREAM_STOP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) (be->dpcm[dir].users >= 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) snd_soc_dapm_stream_event(be, dir, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) snd_soc_dapm_stream_event(fe, dir, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct snd_soc_dai *soc_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (soc_dai->rate && (soc_dai->driver->symmetric_rates ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) rtd->dai_link->symmetric_rates)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) soc_dai->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = snd_pcm_hw_constraint_single(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) soc_dai->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) dev_err(soc_dai->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) "ASoC: Unable to apply rate constraint: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (soc_dai->channels && (soc_dai->driver->symmetric_channels ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) rtd->dai_link->symmetric_channels)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) soc_dai->channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ret = snd_pcm_hw_constraint_single(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) SNDRV_PCM_HW_PARAM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) soc_dai->channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) dev_err(soc_dai->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) "ASoC: Unable to apply channel symmetry constraint: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^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) if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) rtd->dai_link->symmetric_samplebits)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) soc_dai->sample_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ret = snd_pcm_hw_constraint_single(substream->runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) soc_dai->sample_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) dev_err(soc_dai->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) "ASoC: Unable to apply sample bits symmetry constraint: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct snd_soc_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) unsigned int rate, channels, sample_bits, symmetry, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) rate = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) channels = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) sample_bits = snd_pcm_format_physical_width(params_format(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* reject unmatched parameters when applying symmetry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) symmetry = rtd->dai_link->symmetric_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) for_each_rtd_cpu_dais(rtd, i, dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) symmetry |= dai->driver->symmetric_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (symmetry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (cpu_dai->rate && cpu_dai->rate != rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) cpu_dai->rate, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) symmetry = rtd->dai_link->symmetric_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) for_each_rtd_dais(rtd, i, dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) symmetry |= dai->driver->symmetric_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (symmetry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (cpu_dai->channels &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) cpu_dai->channels != channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) cpu_dai->channels, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) symmetry = rtd->dai_link->symmetric_samplebits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) for_each_rtd_dais(rtd, i, dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) symmetry |= dai->driver->symmetric_samplebits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (symmetry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (cpu_dai->sample_bits &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) cpu_dai->sample_bits != sample_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) cpu_dai->sample_bits, sample_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct snd_soc_dai_link *link = rtd->dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) unsigned int symmetry, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) symmetry = link->symmetric_rates ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) link->symmetric_channels ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) link->symmetric_samplebits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) for_each_rtd_dais(rtd, i, dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) symmetry = symmetry ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dai->driver->symmetric_rates ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) dai->driver->symmetric_channels ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) dai->driver->symmetric_samplebits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return symmetry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (!bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 0, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dev_warn(rtd->dev, "ASoC: Failed to set MSB %d: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) bits, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct snd_soc_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct snd_soc_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) unsigned int bits = 0, cpu_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) for_each_rtd_codec_dais(rtd, i, codec_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (pcm_codec->sig_bits == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) bits = max(pcm_codec->sig_bits, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (pcm_cpu->sig_bits == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) cpu_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) cpu_bits = max(pcm_cpu->sig_bits, cpu_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) soc_pcm_set_msb(substream, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) soc_pcm_set_msb(substream, cpu_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * snd_soc_runtime_calc_hw() - Calculate hw limits for a PCM stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * @rtd: ASoC PCM runtime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * @hw: PCM hardware parameters (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * @stream: Direction of the PCM stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * Calculates the subset of stream parameters supported by all DAIs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * associated with the PCM stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct snd_pcm_hardware *hw, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct snd_soc_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct snd_soc_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct snd_soc_pcm_stream *codec_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct snd_soc_pcm_stream *cpu_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) unsigned int chan_min = 0, chan_max = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) unsigned int cpu_chan_min = 0, cpu_chan_max = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) unsigned int rate_min = 0, rate_max = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) unsigned int cpu_rate_min = 0, cpu_rate_max = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) unsigned int rates = UINT_MAX, cpu_rates = UINT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) u64 formats = ULLONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* first calculate min/max only for CPUs in the DAI link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^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) * Skip CPUs which don't support the current stream type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * Otherwise, since the rate, channel, and format values will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * zero in that case, we would have no usable settings left,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * causing the resulting setup to fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (!snd_soc_dai_stream_valid(cpu_dai, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) cpu_stream = snd_soc_dai_get_pcm_stream(cpu_dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) cpu_chan_min = max(cpu_chan_min, cpu_stream->channels_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) cpu_chan_max = min(cpu_chan_max, cpu_stream->channels_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) cpu_rate_min = max(cpu_rate_min, cpu_stream->rate_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) cpu_rate_max = min_not_zero(cpu_rate_max, cpu_stream->rate_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) formats &= cpu_stream->formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) cpu_rates = snd_pcm_rate_mask_intersect(cpu_stream->rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) cpu_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* second calculate min/max only for CODECs in the DAI link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) for_each_rtd_codec_dais(rtd, i, codec_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * Skip CODECs which don't support the current stream type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * Otherwise, since the rate, channel, and format values will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * zero in that case, we would have no usable settings left,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * causing the resulting setup to fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!snd_soc_dai_stream_valid(codec_dai, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) codec_stream = snd_soc_dai_get_pcm_stream(codec_dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) chan_min = max(chan_min, codec_stream->channels_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) chan_max = min(chan_max, codec_stream->channels_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) rate_min = max(rate_min, codec_stream->rate_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) rate_max = min_not_zero(rate_max, codec_stream->rate_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) formats &= codec_stream->formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) rates = snd_pcm_rate_mask_intersect(codec_stream->rates, rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* Verify both a valid CPU DAI and a valid CODEC DAI were found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!chan_min || !cpu_chan_min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * chan min/max cannot be enforced if there are multiple CODEC DAIs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * connected to CPU DAI(s), use CPU DAI's directly and let
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * channel allocation be fixed up later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (rtd->num_codecs > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) chan_min = cpu_chan_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) chan_max = cpu_chan_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* finally find a intersection between CODECs and CPUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) hw->channels_min = max(chan_min, cpu_chan_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) hw->channels_max = min(chan_max, cpu_chan_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) hw->formats = formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) hw->rates = snd_pcm_rate_mask_intersect(rates, cpu_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) snd_pcm_hw_limit_rates(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) hw->rate_min = max(hw->rate_min, cpu_rate_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) hw->rate_min = max(hw->rate_min, rate_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) hw->rate_max = min_not_zero(hw->rate_max, cpu_rate_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) hw->rate_max = min_not_zero(hw->rate_max, rate_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) EXPORT_SYMBOL_GPL(snd_soc_runtime_calc_hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct snd_pcm_hardware *hw = &substream->runtime->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) u64 formats = hw->formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * At least one CPU and one CODEC should match. Otherwise, we should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * have bailed out on a higher level, since there would be no CPU or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * CODEC to support the transfer direction in that case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) snd_soc_runtime_calc_hw(rtd, hw, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) hw->formats &= formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static int soc_pcm_components_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) for_each_rtd_components(rtd, i, component) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ret = snd_soc_component_module_get_when_open(component, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) ret = snd_soc_component_open(component, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) break;
^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) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static int soc_pcm_components_close(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) int rollback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) int i, r, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) for_each_rtd_components(rtd, i, component) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) r = snd_soc_component_close(component, substream, rollback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (r < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) ret = r; /* use last ret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) snd_soc_component_module_put_when_close(component, substream, rollback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static int soc_pcm_clean(struct snd_pcm_substream *substream, int rollback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (!rollback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) snd_soc_runtime_deactivate(rtd, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) for_each_rtd_dais(rtd, i, dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) snd_soc_dai_shutdown(dai, substream, rollback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) snd_soc_link_shutdown(substream, rollback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) soc_pcm_components_close(substream, rollback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (!rollback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) snd_soc_dapm_stream_stop(rtd, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) mutex_unlock(&rtd->card->pcm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) snd_soc_pcm_component_pm_runtime_put(rtd, substream, rollback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) for_each_rtd_components(rtd, i, component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (!snd_soc_component_active(component))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) pinctrl_pm_select_sleep_state(component->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * Called by ALSA when a PCM substream is closed. Private data can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * freed here. The cpu DAI, codec DAI, machine and components are also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * shutdown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static int soc_pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return soc_pcm_clean(substream, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * Called by ALSA when a PCM substream is opened, the runtime->hw record is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * then initialized and any private data can be allocated. This also calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * startup for the cpu DAI, component, machine and codec DAI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static int soc_pcm_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) const char *codec_dai_name = "multicodec";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) const char *cpu_dai_name = "multicpu";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) for_each_rtd_components(rtd, i, component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) pinctrl_pm_select_default_state(component->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ret = snd_soc_pcm_component_pm_runtime_get(rtd, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) goto pm_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ret = soc_pcm_components_open(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ret = snd_soc_link_startup(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /* startup the audio subsystem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) for_each_rtd_dais(rtd, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ret = snd_soc_dai_startup(dai, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) dai->tx_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) dai->rx_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* Dynamic PCM DAI links compat checks use dynamic capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) goto dynamic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /* Check that the codec and cpu DAIs are compatible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) soc_pcm_init_runtime_hw(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (rtd->num_codecs == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) codec_dai_name = asoc_rtd_to_codec(rtd, 0)->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (rtd->num_cpus == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) cpu_dai_name = asoc_rtd_to_cpu(rtd, 0)->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (soc_pcm_has_symmetry(substream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (!runtime->hw.rates) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) codec_dai_name, cpu_dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (!runtime->hw.formats) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) codec_dai_name, cpu_dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (!runtime->hw.channels_min || !runtime->hw.channels_max ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) runtime->hw.channels_min > runtime->hw.channels_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) codec_dai_name, cpu_dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) goto err;
^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) soc_pcm_apply_msb(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /* Symmetry only applies if we've already got an active stream. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) for_each_rtd_dais(rtd, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (snd_soc_dai_active(dai)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) ret = soc_pcm_apply_symmetry(substream, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) goto err;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) pr_debug("ASoC: %s <-> %s info:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) codec_dai_name, cpu_dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) runtime->hw.channels_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) pr_debug("ASoC: min rate %d max rate %d\n", runtime->hw.rate_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) runtime->hw.rate_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) dynamic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) snd_soc_runtime_activate(rtd, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) mutex_unlock(&rtd->card->pcm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) pm_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) soc_pcm_clean(substream, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * Currently nothing to do for c2c links
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * Since c2c links are internal nodes in the DAPM graph and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * don't interface with the outside world or application layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * we don't have to do any special handling on close.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * Called by ALSA when the PCM substream is prepared, can set format, sample
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * rate, etc. This function is non atomic and can be called multiple times,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * it can refer to the runtime info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static int soc_pcm_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ret = snd_soc_link_prepare(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) ret = snd_soc_pcm_component_prepare(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ret = snd_soc_pcm_dai_prepare(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) dev_err(rtd->dev, "ASoC: DAI prepare error: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) /* cancel any delayed stream shutdown that is pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) rtd->pop_wait) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) rtd->pop_wait = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) cancel_delayed_work(&rtd->delayed_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) snd_soc_dapm_stream_event(rtd, substream->stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) SND_SOC_DAPM_STREAM_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) for_each_rtd_dais(rtd, i, dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) snd_soc_dai_digital_mute(dai, 0, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) mutex_unlock(&rtd->card->pcm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) static void soc_pcm_codec_params_fixup(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) unsigned int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct snd_interval *interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) int channels = hweight_long(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) interval = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) interval->min = channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) interval->max = channels;
^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) * Called by ALSA when the hardware params are set by application. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * function can also be called multiple times and can allocate buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * (using snd_pcm_lib_* ). It's non-atomic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct snd_soc_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct snd_soc_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) ret = soc_pcm_params_symmetry(substream, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) ret = snd_soc_link_hw_params(substream, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) for_each_rtd_codec_dais(rtd, i, codec_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) struct snd_pcm_hw_params codec_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) * Skip CODECs which don't support the current stream type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) * the idea being that if a CODEC is not used for the currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * set up transfer direction, it should not need to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * configured, especially since the configuration used might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * not even be supported by that CODEC. There may be cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * however where a CODEC needs to be set up although it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * actually not being used for the transfer, e.g. if a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * capture-only CODEC is acting as an LRCLK and/or BCLK master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * for the DAI link including a playback-only CODEC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * If this becomes necessary, we will have to augment the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * machine driver setup with information on how to act, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * we can do the right thing here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (!snd_soc_dai_stream_valid(codec_dai, substream->stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /* copy params for each codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) codec_params = *params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) /* fixup params based on TDM slot masks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) codec_dai->tx_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) soc_pcm_codec_params_fixup(&codec_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) codec_dai->tx_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) codec_dai->rx_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) soc_pcm_codec_params_fixup(&codec_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) codec_dai->rx_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) ret = snd_soc_dai_hw_params(codec_dai, substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) &codec_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if(ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) goto codec_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) codec_dai->rate = params_rate(&codec_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) codec_dai->channels = params_channels(&codec_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) codec_dai->sample_bits = snd_pcm_format_physical_width(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) params_format(&codec_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) snd_soc_dapm_update_dai(substream, &codec_params, codec_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * Skip CPUs which don't support the current stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * type. See soc_pcm_init_runtime_hw() for more details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) ret = snd_soc_dai_hw_params(cpu_dai, substream, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) goto interface_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /* store the parameters for each DAI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) cpu_dai->rate = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) cpu_dai->channels = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) cpu_dai->sample_bits =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) snd_pcm_format_physical_width(params_format(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) snd_soc_dapm_update_dai(substream, params, cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) ret = snd_soc_pcm_component_hw_params(substream, params, &component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) goto component_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) mutex_unlock(&rtd->card->pcm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) component_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) snd_soc_pcm_component_hw_free(substream, component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) i = rtd->num_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) interface_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) for_each_rtd_cpu_dais_rollback(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) snd_soc_dai_hw_free(cpu_dai, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) cpu_dai->rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) i = rtd->num_codecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) codec_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) for_each_rtd_codec_dais_rollback(rtd, i, codec_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (!snd_soc_dai_stream_valid(codec_dai, substream->stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) snd_soc_dai_hw_free(codec_dai, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) codec_dai->rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) snd_soc_link_hw_free(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) mutex_unlock(&rtd->card->pcm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * Frees resources allocated by hw_params, can be called multiple times
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* clear the corresponding DAIs parameters when going to be inactive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) for_each_rtd_dais(rtd, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) int active = snd_soc_dai_stream_active(dai, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (snd_soc_dai_active(dai) == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) dai->rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) dai->channels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) dai->sample_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (active == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) snd_soc_dai_digital_mute(dai, 1, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /* free any machine hw params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) snd_soc_link_hw_free(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) /* free any component resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) snd_soc_pcm_component_hw_free(substream, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /* now free hw params for the DAIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) for_each_rtd_dais(rtd, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (!snd_soc_dai_stream_valid(dai, substream->stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) snd_soc_dai_hw_free(dai, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) mutex_unlock(&rtd->card->pcm_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) ret = snd_soc_link_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) ret = snd_soc_pcm_component_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) ret = snd_soc_pcm_dai_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) ret = snd_soc_pcm_dai_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) ret = snd_soc_pcm_component_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) ret = snd_soc_link_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) break;
^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 ret;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * soc level wrapper for pointer callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * If cpu_dai, codec_dai, component driver has the delay callback, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * the runtime->delay will be updated accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) struct snd_soc_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) struct snd_soc_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) snd_pcm_uframes_t offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) snd_pcm_sframes_t delay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) snd_pcm_sframes_t codec_delay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) snd_pcm_sframes_t cpu_delay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /* clearing the previous total delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) runtime->delay = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) offset = snd_soc_pcm_component_pointer(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) /* base delay if assigned in pointer callback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) delay = runtime->delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) cpu_delay = max(cpu_delay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) snd_soc_dai_delay(cpu_dai, substream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) delay += cpu_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) for_each_rtd_codec_dais(rtd, i, codec_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) codec_delay = max(codec_delay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) snd_soc_dai_delay(codec_dai, substream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) delay += codec_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) runtime->delay = delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /* connect a FE and BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) struct snd_soc_pcm_runtime *be, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) /* only add new dpcms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (dpcm->be == be && dpcm->fe == fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) dpcm = kzalloc(sizeof(struct snd_soc_dpcm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (!dpcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) dpcm->be = be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) dpcm->fe = fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) spin_lock_irqsave(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) stream ? "capture" : "playback", fe->dai_link->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) stream ? "<-" : "->", be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) dpcm_create_debugfs_state(dpcm, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /* reparent a BE onto another FE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) struct snd_soc_pcm_runtime *be, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) struct snd_pcm_substream *fe_substream, *be_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) /* reparent if BE is connected to other FEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (!be->dpcm[stream].users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) be_substream = snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) for_each_dpcm_fe(be, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (dpcm->fe == fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) dev_dbg(fe->dev, "reparent %s path %s %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) stream ? "capture" : "playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) dpcm->fe->dai_link->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) stream ? "<-" : "->", dpcm->be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) be_substream->runtime = fe_substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^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) /* disconnect a BE and FE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) struct snd_soc_dpcm *dpcm, *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) for_each_dpcm_be_safe(fe, stream, dpcm, d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) stream ? "capture" : "playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) dpcm->be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (dpcm->state != SND_SOC_DPCM_LINK_STATE_FREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) dev_dbg(fe->dev, "freed DSP %s path %s %s %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) stream ? "capture" : "playback", fe->dai_link->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) stream ? "<-" : "->", dpcm->be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) /* BEs still alive need new FE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) dpcm_be_reparent(fe, dpcm->be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) dpcm_remove_debugfs_state(dpcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) spin_lock_irqsave(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) list_del(&dpcm->list_be);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) list_del(&dpcm->list_fe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) kfree(dpcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) /* get BE for DAI widget and stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) struct snd_soc_dapm_widget *widget, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) struct snd_soc_pcm_runtime *be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) dev_dbg(card->dev, "ASoC: find BE for widget %s\n", widget->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) for_each_card_rtds(card, be) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (!be->dai_link->no_pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) for_each_rtd_dais(be, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) w = snd_soc_dai_get_widget(dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) dev_dbg(card->dev, "ASoC: try BE : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) w ? w->name : "(not set)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (w == widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) return be;
^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 provided is not a BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) static int widget_in_list(struct snd_soc_dapm_widget_list *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) struct snd_soc_dapm_widget *widget)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) struct snd_soc_dapm_widget *w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) for_each_dapm_widgets(list, i, w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (widget == w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) static bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) enum snd_soc_dapm_direction dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) struct snd_soc_card *card = widget->dapm->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) struct snd_soc_pcm_runtime *rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) int stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) /* adjust dir to stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (dir == SND_SOC_DAPM_DIR_OUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) stream = SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) stream = SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) rtd = dpcm_get_be(card, widget, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (rtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) int stream, struct snd_soc_dapm_widget_list **list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) int paths;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) bool chaining = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (fe->num_cpus > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) dev_err(fe->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) "%s doesn't support Multi CPU yet\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) trace_android_vh_snd_soc_card_get_comp_chain(&chaining);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) /* get number of valid DAI paths and their widgets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) chaining ? NULL : dpcm_end_walk_at_be);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) stream ? "capture" : "playback");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) return paths;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) snd_soc_dapm_dai_free_widgets(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) static bool dpcm_be_is_active(struct snd_soc_dpcm *dpcm, int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) struct snd_soc_dapm_widget_list *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) struct snd_soc_dapm_widget *widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) /* is there a valid DAI widget for this BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) for_each_rtd_dais(dpcm->be, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) widget = snd_soc_dai_get_widget(dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) * The BE is pruned only if none of the dai
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * widgets are in the active list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (widget && widget_in_list(list, widget))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) struct snd_soc_dapm_widget_list **list_)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) int prune = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /* Destroy any old FE <--> BE connections */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (dpcm_be_is_active(dpcm, stream, *list_))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) stream ? "capture" : "playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) dpcm->be->dai_link->name, fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) dpcm->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) prune++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) dev_dbg(fe->dev, "ASoC: found %d old BE paths for pruning\n", prune);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) return prune;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) struct snd_soc_dapm_widget_list **list_)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) struct snd_soc_card *card = fe->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) struct snd_soc_dapm_widget_list *list = *list_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) struct snd_soc_pcm_runtime *be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) struct snd_soc_dapm_widget *widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) int i, new = 0, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) /* Create any new FE <--> BE connections */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) for_each_dapm_widgets(list, i, widget) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) switch (widget->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) case snd_soc_dapm_dai_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (stream != SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) case snd_soc_dapm_dai_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (stream != SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) /* is there a valid BE rtd for this widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) be = dpcm_get_be(card, widget, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (!be) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) dev_err(fe->dev, "ASoC: no BE found for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) widget->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) /* don't connect if FE is not running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (!fe->dpcm[stream].runtime && !fe->fe_compr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) /* newly connected FE and BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) err = dpcm_be_connect(fe, be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) dev_err(fe->dev, "ASoC: can't connect %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) widget->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) } else if (err == 0) /* already connected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) /* new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) new++;
^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) dev_dbg(fe->dev, "ASoC: found %d new BE paths\n", new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) * Find the corresponding BE DAIs that source or sink audio to this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) * FE substream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) int stream, struct snd_soc_dapm_widget_list **list, int new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) if (new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) return dpcm_add_paths(fe, stream, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return dpcm_prune_paths(fe, stream, list);
^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) void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) spin_lock_irqsave(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) for_each_dpcm_be(fe, stream, dpcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) dpcm->be->dpcm[stream].runtime_update =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) SND_SOC_DPCM_UPDATE_NO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) /* disable any enabled and non active backends */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (be->dpcm[stream].users == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) dev_err(be->dev, "ASoC: no users %s at close - state %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) stream ? "capture" : "playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) be->dpcm[stream].state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (--be->dpcm[stream].users != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) soc_pcm_close(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) be_substream->runtime = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) int err, count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) /* only startup BE DAIs that are either sinks or sources to this FE DAI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (!be_substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) dev_err(be->dev, "ASoC: no backend %s stream\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) stream ? "capture" : "playback");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /* is this op for this BE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) /* first time the dpcm is open ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (be->dpcm[stream].users == DPCM_MAX_BE_USERS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) dev_err(be->dev, "ASoC: too many users %s at open %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) stream ? "capture" : "playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) be->dpcm[stream].state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) if (be->dpcm[stream].users++ != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) dev_dbg(be->dev, "ASoC: open %s BE %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) stream ? "capture" : "playback", be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) be_substream->runtime = be->dpcm[stream].runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) err = soc_pcm_open(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) dev_err(be->dev, "ASoC: BE open failed %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) be->dpcm[stream].users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) if (be->dpcm[stream].users < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) dev_err(be->dev, "ASoC: no users %s at unwind %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) stream ? "capture" : "playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) be->dpcm[stream].state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) goto unwind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) unwind:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) /* disable any enabled and non active backends */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) for_each_dpcm_be_rollback(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if (be->dpcm[stream].users == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) dev_err(be->dev, "ASoC: no users %s at close %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) stream ? "capture" : "playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) be->dpcm[stream].state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (--be->dpcm[stream].users != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) soc_pcm_close(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) be_substream->runtime = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) struct snd_soc_pcm_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) runtime->hw.rate_min = stream->rate_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) runtime->hw.rate_max = min_not_zero(stream->rate_max, UINT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) runtime->hw.channels_min = stream->channels_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) runtime->hw.channels_max = stream->channels_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (runtime->hw.formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) runtime->hw.formats &= stream->formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) runtime->hw.formats = stream->formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) runtime->hw.rates = stream->rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) u64 *formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) int stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if (!fe->dai_link->dpcm_merged_format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) * It returns merged BE codec format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) * if FE want to use it (= dpcm_merged_format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) struct snd_soc_pcm_stream *codec_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) for_each_rtd_codec_dais(be, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) * Skip CODECs which don't support the current stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) * type. See soc_pcm_init_runtime_hw() for more details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) if (!snd_soc_dai_stream_valid(dai, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) codec_stream = snd_soc_dai_get_pcm_stream(dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) *formats &= codec_stream->formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) unsigned int *channels_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) unsigned int *channels_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) int stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (!fe->dai_link->dpcm_merged_chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) * It returns merged BE codec channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) * if FE want to use it (= dpcm_merged_chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) struct snd_soc_pcm_stream *codec_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) struct snd_soc_pcm_stream *cpu_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) for_each_rtd_cpu_dais(be, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) * Skip CPUs which don't support the current stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) * type. See soc_pcm_init_runtime_hw() for more details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) if (!snd_soc_dai_stream_valid(dai, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) *channels_min = max(*channels_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) cpu_stream->channels_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) *channels_max = min(*channels_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) cpu_stream->channels_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) * chan min/max cannot be enforced if there are multiple CODEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) * DAIs connected to a single CPU DAI, use CPU DAI's directly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) if (be->num_codecs == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) *channels_min = max(*channels_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) codec_stream->channels_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) *channels_max = min(*channels_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) codec_stream->channels_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) unsigned int *rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) unsigned int *rate_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) unsigned int *rate_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) int stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) if (!fe->dai_link->dpcm_merged_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) * It returns merged BE codec channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) * if FE want to use it (= dpcm_merged_chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) struct snd_soc_pcm_stream *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) for_each_rtd_dais(be, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) * Skip DAIs which don't support the current stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) * type. See soc_pcm_init_runtime_hw() for more details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) if (!snd_soc_dai_stream_valid(dai, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) pcm = snd_soc_dai_get_pcm_stream(dai, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) *rate_min = max(*rate_min, pcm->rate_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) *rate_max = min_not_zero(*rate_max, pcm->rate_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) *rates = snd_pcm_rate_mask_intersect(*rates, pcm->rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) struct snd_soc_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) * Skip CPUs which don't support the current stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) * type. See soc_pcm_init_runtime_hw() for more details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) dpcm_init_runtime_hw(runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) snd_soc_dai_get_pcm_stream(cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) substream->stream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) dpcm_runtime_merge_format(substream, &runtime->hw.formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) dpcm_runtime_merge_chan(substream, &runtime->hw.channels_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) &runtime->hw.channels_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) dpcm_runtime_merge_rate(substream, &runtime->hw.rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) &runtime->hw.rate_min, &runtime->hw.rate_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) /* Set FE's runtime_update state; the state is protected via PCM stream lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) * for avoiding the race with trigger callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) * If the state is unset and a trigger is pending while the previous operation,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) * process the pending trigger action here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) int stream, enum snd_soc_dpcm_update state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) struct snd_pcm_substream *substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) snd_soc_dpcm_get_substream(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) snd_pcm_stream_lock_irq(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) dpcm_fe_dai_do_trigger(substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) fe->dpcm[stream].trigger_pending - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) fe->dpcm[stream].trigger_pending = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) fe->dpcm[stream].runtime_update = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) snd_pcm_stream_unlock_irq(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) struct snd_soc_dai *fe_cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) /* apply symmetry for FE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) if (soc_pcm_has_symmetry(fe_substream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) fe_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) for_each_rtd_cpu_dais (fe, i, fe_cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) /* Symmetry only applies if we've got an active stream. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) if (snd_soc_dai_active(fe_cpu_dai)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) }
^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) /* apply symmetry for BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) struct snd_soc_pcm_runtime *rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) /* A backend may not have the requested substream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) if (!be_substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) rtd = asoc_substream_to_rtd(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) if (rtd->dai_link->be_hw_params_fixup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) if (soc_pcm_has_symmetry(be_substream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) /* Symmetry only applies if we've got an active stream. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) for_each_rtd_dais(rtd, i, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) if (snd_soc_dai_active(dai)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) err = soc_pcm_apply_symmetry(fe_substream, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) return err;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) struct snd_pcm_runtime *runtime = fe_substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) int stream = fe_substream->stream, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) ret = dpcm_be_dai_startup(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) dev_err(fe->dev,"ASoC: failed to start some BEs %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) goto be_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) dev_dbg(fe->dev, "ASoC: open FE %s\n", fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) /* start the DAI frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) ret = soc_pcm_open(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) dev_err(fe->dev,"ASoC: failed to start FE %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) goto unwind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) dpcm_set_fe_runtime(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) snd_pcm_limit_hw_rates(runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) ret = dpcm_apply_symmetry(fe_substream, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) dev_err(fe->dev, "ASoC: failed to apply dpcm symmetry %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) unwind:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) dpcm_be_dai_startup_unwind(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) be_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) /* only shutdown BEs that are either sinks or sources to this FE DAI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) /* is this op for this BE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) if (be->dpcm[stream].users == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) dev_err(be->dev, "ASoC: no users %s at close - state %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) stream ? "capture" : "playback",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) be->dpcm[stream].state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) if (--be->dpcm[stream].users != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) soc_pcm_hw_free(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) dev_dbg(be->dev, "ASoC: close BE %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) soc_pcm_close(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) be_substream->runtime = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) int stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) /* shutdown the BEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) dpcm_be_dai_shutdown(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) dev_dbg(fe->dev, "ASoC: close FE %s\n", fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) /* now shutdown the frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) soc_pcm_close(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) /* run the stream event for each BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) /* only hw_params backends that are either sinks or sources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) * to this frontend DAI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) /* is this op for this BE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) /* only free hw when no longer used - check all FEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) /* do not free hw if this BE is used by other FE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) if (be->dpcm[stream].users > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) soc_pcm_hw_free(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) int err, stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) /* call hw_free on the frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) err = soc_pcm_hw_free(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) dev_err(fe->dev,"ASoC: hw_free FE %s failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) /* only hw_params backends that are either sinks or sources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) * to this frontend DAI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) err = dpcm_be_dai_hw_free(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) mutex_unlock(&fe->card->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) /* is this op for this BE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) /* copy params for each dpcm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) memcpy(&dpcm->hw_params, &fe->dpcm[stream].hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) sizeof(struct snd_pcm_hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) /* perform any hw_params fixups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) ret = snd_soc_link_be_hw_params_fixup(be, &dpcm->hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) goto unwind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) /* copy the fixed-up hw params for BE dai */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) memcpy(&be->dpcm[stream].hw_params, &dpcm->hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) sizeof(struct snd_pcm_hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) /* only allow hw_params() if no connected FEs are running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) if (!snd_soc_dpcm_can_be_params(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) dev_dbg(be->dev, "ASoC: hw_params BE %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) dev_err(dpcm->be->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) "ASoC: hw_params BE failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) goto unwind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) unwind:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) /* disable any enabled and non active backends */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) for_each_dpcm_be_rollback(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) /* only allow hw_free() if no connected FEs are running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) soc_pcm_hw_free(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) int ret, stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) memcpy(&fe->dpcm[stream].hw_params, params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) sizeof(struct snd_pcm_hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) ret = dpcm_be_dai_hw_params(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) dev_err(fe->dev,"ASoC: hw_params BE failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) dev_dbg(fe->dev, "ASoC: hw_params FE %s rate %d chan %x fmt %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) fe->dai_link->name, params_rate(params),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) params_channels(params), params_format(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) /* call hw_params on the frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) ret = soc_pcm_hw_params(substream, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) dev_err(fe->dev,"ASoC: hw_params FE failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) dpcm_be_dai_hw_free(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) mutex_unlock(&fe->card->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) dev_dbg(dpcm->be->dev, "ASoC: trigger BE %s cmd %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) dpcm->be->dai_link->name, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) ret = soc_pcm_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) dev_err(dpcm->be->dev,"ASoC: trigger BE failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) /* is this op for this BE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) ret = dpcm_do_trigger(dpcm, be_substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) ret = dpcm_do_trigger(dpcm, be_substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) ret = dpcm_do_trigger(dpcm, be_substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_START) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
^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) if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) ret = dpcm_do_trigger(dpcm, be_substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) ret = dpcm_do_trigger(dpcm, be_substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) ret = dpcm_do_trigger(dpcm, be_substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) static int dpcm_dai_trigger_fe_be(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) int cmd, bool fe_first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) /* call trigger on the frontend before the backend. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) if (fe_first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) dev_dbg(fe->dev, "ASoC: pre trigger FE %s cmd %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) fe->dai_link->name, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) ret = soc_pcm_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) /* call trigger on the frontend after the backend. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) dev_dbg(fe->dev, "ASoC: post trigger FE %s cmd %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) fe->dai_link->name, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) ret = soc_pcm_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) int stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) switch (trigger) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) case SND_SOC_DPCM_TRIGGER_PRE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) case SNDRV_PCM_TRIGGER_DRAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) case SND_SOC_DPCM_TRIGGER_POST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) case SNDRV_PCM_TRIGGER_DRAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) ret = dpcm_dai_trigger_fe_be(substream, cmd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) ret = dpcm_dai_trigger_fe_be(substream, cmd, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) case SND_SOC_DPCM_TRIGGER_BESPOKE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) /* bespoke trigger() - handles both FE and BEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) fe->dai_link->name, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) ret = snd_soc_pcm_dai_bespoke_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) dev_err(fe->dev, "ASoC: trigger FE cmd: %d failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) cmd, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) int stream = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) /* if FE's runtime_update is already set, we're in race;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) * process this trigger later at exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) if (fe->dpcm[stream].runtime_update != SND_SOC_DPCM_UPDATE_NO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) fe->dpcm[stream].trigger_pending = cmd + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) return 0; /* delayed, assuming it's successful */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) /* we're alone, let's trigger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) return dpcm_fe_dai_do_trigger(substream, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) struct snd_pcm_substream *be_substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) snd_soc_dpcm_get_substream(be, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) /* is this op for this BE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) if (!snd_soc_dpcm_be_can_update(fe, be, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) dev_dbg(be->dev, "ASoC: prepare BE %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) be->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) ret = soc_pcm_prepare(be_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) dev_err(be->dev, "ASoC: backend prepare failed %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) return ret;
^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) static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) int stream = substream->stream, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) /* there is no point preparing this FE if there are no BEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) if (list_empty(&fe->dpcm[stream].be_clients)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) dev_err(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) ret = dpcm_be_dai_prepare(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) /* call prepare on the frontend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) ret = soc_pcm_prepare(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) dev_err(fe->dev,"ASoC: prepare FE %s failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) /* run the stream event for each BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) mutex_unlock(&fe->card->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) struct snd_pcm_substream *substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) snd_soc_dpcm_get_substream(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) dev_dbg(fe->dev, "ASoC: runtime %s close on FE %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) stream ? "capture" : "playback", fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) /* call bespoke trigger - FE takes care of all BE triggers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) dev_dbg(fe->dev, "ASoC: trigger FE %s cmd stop\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) err = dpcm_be_dai_hw_free(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) dev_err(fe->dev,"ASoC: hw_free FE failed %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) err = dpcm_be_dai_shutdown(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) dev_err(fe->dev,"ASoC: shutdown FE failed %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) /* run the stream event for each BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) return 0;
^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) static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) struct snd_pcm_substream *substream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) snd_soc_dpcm_get_substream(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) stream ? "capture" : "playback", fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) /* Only start the BE if the FE is ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) /* startup must always be called for new BEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) ret = dpcm_be_dai_startup(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) goto disconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) /* keep going if FE state is > open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) ret = dpcm_be_dai_hw_params(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) goto close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) /* keep going if FE state is > hw_params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) ret = dpcm_be_dai_prepare(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) goto hw_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) /* run the stream event for each BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) /* keep going if FE state is > prepare */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_PREPARE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) /* call trigger on the frontend - FE takes care of all BE triggers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) dev_err(fe->dev,"ASoC: bespoke trigger FE failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) goto hw_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) dev_dbg(fe->dev, "ASoC: trigger FE %s cmd start\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) ret = dpcm_be_dai_trigger(fe, stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) SNDRV_PCM_TRIGGER_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) goto hw_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) hw_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) dpcm_be_dai_hw_free(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) dpcm_be_dai_shutdown(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) disconnect:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) /* disconnect any closed BEs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) spin_lock_irqsave(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) for_each_dpcm_be(fe, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) struct snd_soc_pcm_runtime *be = dpcm->be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) struct snd_soc_dapm_widget_list *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) int stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) int count, paths;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) if (!fe->dai_link->dynamic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) if (fe->num_cpus > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) dev_err(fe->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) "%s doesn't support Multi CPU yet\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) /* only check active links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) if (!snd_soc_dai_active(asoc_rtd_to_cpu(fe, 0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) /* DAPM sync will call this to update DSP paths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) dev_dbg(fe->dev, "ASoC: DPCM %s runtime update for FE %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) new ? "new" : "old", fe->dai_link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) for_each_pcm_streams(stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) /* skip if FE doesn't have playback/capture capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) if (!snd_soc_dai_stream_valid(asoc_rtd_to_cpu(fe, 0), stream) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) !snd_soc_dai_stream_valid(asoc_rtd_to_codec(fe, 0), stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) /* skip if FE isn't currently playing/capturing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) if (!snd_soc_dai_stream_active(asoc_rtd_to_cpu(fe, 0), stream) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) !snd_soc_dai_stream_active(asoc_rtd_to_codec(fe, 0), stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) paths = dpcm_path_get(fe, stream, &list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) if (paths < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) dev_warn(fe->dev, "ASoC: %s no valid %s path\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) fe->dai_link->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) stream == SNDRV_PCM_STREAM_PLAYBACK ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) "playback" : "capture");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) return paths;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) /* update any playback/capture paths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) count = dpcm_process_paths(fe, stream, &list, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) if (new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) ret = dpcm_run_update_startup(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) ret = dpcm_run_update_shutdown(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) dpcm_clear_pending_state(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) dpcm_be_disconnect(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) dpcm_path_put(&list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) /* Called by DAPM mixer/mux changes to update audio routing between PCMs and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) * any DAI links.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) int snd_soc_dpcm_runtime_update(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) struct snd_soc_pcm_runtime *fe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) /* shutdown all old paths first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) for_each_card_rtds(card, fe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) ret = soc_dpcm_fe_runtime_update(fe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) /* bring new paths up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) for_each_card_rtds(card, fe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) ret = soc_dpcm_fe_runtime_update(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) mutex_unlock(&card->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) EXPORT_SYMBOL_GPL(snd_soc_dpcm_runtime_update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) static void dpcm_fe_dai_cleanup(struct snd_pcm_substream *fe_substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) int stream = fe_substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) /* mark FE's links ready to prune */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) for_each_dpcm_be(fe, stream, dpcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) dpcm_be_disconnect(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) fe->dpcm[stream].runtime = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) ret = dpcm_fe_dai_shutdown(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) dpcm_fe_dai_cleanup(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) mutex_unlock(&fe->card->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) struct snd_soc_dapm_widget_list *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) int stream = fe_substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) fe->dpcm[stream].runtime = fe_substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) ret = dpcm_path_get(fe, stream, &list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) goto open_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) } else if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) fe->dai_link->name, stream ? "capture" : "playback");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) /* calculate valid and active FE <-> BE dpcms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) dpcm_process_paths(fe, stream, &list, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) ret = dpcm_fe_dai_startup(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) dpcm_fe_dai_cleanup(fe_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) dpcm_clear_pending_state(fe, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) dpcm_path_put(&list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) open_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) mutex_unlock(&fe->card->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) /* create a new pcm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) struct snd_soc_dai *codec_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) struct snd_soc_dai *cpu_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) char new_name[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) int ret = 0, playback = 0, capture = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) int stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) if (rtd->dai_link->dynamic && rtd->num_cpus > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) dev_err(rtd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) "DPCM doesn't support Multi CPU for Front-Ends yet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) if (rtd->dai_link->dpcm_playback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) stream = SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) playback = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) break;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) if (!playback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) dev_err(rtd->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) "No CPU DAIs support playback for stream %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) rtd->dai_link->stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) if (rtd->dai_link->dpcm_capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) stream = SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) capture = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) if (!capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) dev_err(rtd->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) "No CPU DAIs support capture for stream %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) rtd->dai_link->stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) /* Adapt stream for codec2codec links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) int cpu_capture = rtd->dai_link->params ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) int cpu_playback = rtd->dai_link->params ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) for_each_rtd_codec_dais(rtd, i, codec_dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) if (rtd->num_cpus == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) } else if (rtd->num_cpus == rtd->num_codecs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) cpu_dai = asoc_rtd_to_cpu(rtd, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) dev_err(rtd->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) "N cpus to M codecs link is not supported yet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) snd_soc_dai_stream_valid(cpu_dai, cpu_playback))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) playback = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) snd_soc_dai_stream_valid(cpu_dai, cpu_capture))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) capture = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) if (rtd->dai_link->playback_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) playback = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) capture = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) if (rtd->dai_link->capture_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) playback = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) capture = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) /* create the PCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) if (rtd->dai_link->params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) snprintf(new_name, sizeof(new_name), "codec2codec(%s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) rtd->dai_link->stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) playback, capture, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) } else if (rtd->dai_link->no_pcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) snprintf(new_name, sizeof(new_name), "(%s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) rtd->dai_link->stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) playback, capture, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) if (rtd->dai_link->dynamic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) snprintf(new_name, sizeof(new_name), "%s (*)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) rtd->dai_link->stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) snprintf(new_name, sizeof(new_name), "%s %s-%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) rtd->dai_link->stream_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) (rtd->num_codecs > 1) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) capture, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) dev_err(rtd->card->dev, "ASoC: can't create pcm %s for dailink %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) new_name, rtd->dai_link->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) /* DAPM dai link stream work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) if (rtd->dai_link->params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) rtd->close_delayed_work_func = codec2codec_close_delayed_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) rtd->close_delayed_work_func = snd_soc_close_delayed_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) pcm->nonatomic = rtd->dai_link->nonatomic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) rtd->pcm = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) pcm->private_data = rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) if (rtd->dai_link->no_pcm || rtd->dai_link->params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) if (playback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) if (capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) /* ASoC PCM operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) if (rtd->dai_link->dynamic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) rtd->ops.open = dpcm_fe_dai_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) rtd->ops.hw_params = dpcm_fe_dai_hw_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) rtd->ops.prepare = dpcm_fe_dai_prepare;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) rtd->ops.trigger = dpcm_fe_dai_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) rtd->ops.hw_free = dpcm_fe_dai_hw_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) rtd->ops.close = dpcm_fe_dai_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) rtd->ops.pointer = soc_pcm_pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) rtd->ops.open = soc_pcm_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) rtd->ops.hw_params = soc_pcm_hw_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) rtd->ops.prepare = soc_pcm_prepare;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) rtd->ops.trigger = soc_pcm_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) rtd->ops.hw_free = soc_pcm_hw_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) rtd->ops.close = soc_pcm_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) rtd->ops.pointer = soc_pcm_pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) for_each_rtd_components(rtd, i, component) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) const struct snd_soc_component_driver *drv = component->driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) if (drv->ioctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) rtd->ops.ioctl = snd_soc_pcm_component_ioctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) if (drv->sync_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) rtd->ops.sync_stop = snd_soc_pcm_component_sync_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) if (drv->copy_user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) rtd->ops.copy_user = snd_soc_pcm_component_copy_user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) if (drv->page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) rtd->ops.page = snd_soc_pcm_component_page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) if (drv->mmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) rtd->ops.mmap = snd_soc_pcm_component_mmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) if (drv->ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) rtd->ops.ack = snd_soc_pcm_component_ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) if (playback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) if (capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) ret = snd_soc_pcm_component_new(rtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) dev_err(rtd->dev, "ASoC: pcm %s constructor failed for dailink %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) new_name, rtd->dai_link->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) pcm->no_device_suspend = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) /* is the current PCM operation for this FE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) if (fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) EXPORT_SYMBOL_GPL(snd_soc_dpcm_fe_can_update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) /* is the current PCM operation for this BE ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) struct snd_soc_pcm_runtime *be, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) if ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_BE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) be->dpcm[stream].runtime_update))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_can_update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) /* get the substream for this BE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) struct snd_pcm_substream *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) return be->pcm->streams[stream].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) EXPORT_SYMBOL_GPL(snd_soc_dpcm_get_substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) static int snd_soc_dpcm_check_state(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) struct snd_soc_pcm_runtime *be,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) int stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) const enum snd_soc_dpcm_state *states,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) int num_states)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) struct snd_soc_dpcm *dpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) int ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) spin_lock_irqsave(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) for_each_dpcm_fe(be, stream, dpcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) if (dpcm->fe == fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) state = dpcm->fe->dpcm[stream].state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) for (i = 0; i < num_states; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) if (state == states[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) /* it's safe to do this BE DAI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) }
^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) * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) * are not running, paused or suspended for the specified stream direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) struct snd_soc_pcm_runtime *be, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) const enum snd_soc_dpcm_state state[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) SND_SOC_DPCM_STATE_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) SND_SOC_DPCM_STATE_PAUSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) SND_SOC_DPCM_STATE_SUSPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) * We can only change hw params a BE DAI if any of it's FE are not prepared,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) * running, paused or suspended for the specified stream direction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) struct snd_soc_pcm_runtime *be, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) const enum snd_soc_dpcm_state state[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) SND_SOC_DPCM_STATE_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) SND_SOC_DPCM_STATE_PAUSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) SND_SOC_DPCM_STATE_SUSPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) SND_SOC_DPCM_STATE_PREPARE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);