^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-topology.c -- ALSA SoC Topology
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (C) 2012 Texas Instruments Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Copyright (C) 2015 Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // Authors: Liam Girdwood <liam.r.girdwood@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // K, Mythri P <mythri.p.k@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // Prusty, Subhransu S <subhransu.s.prusty@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // B, Jayachandran <jayachandran.b@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) // Abdullah, Omair M <omair.m.abdullah@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) // Jin, Yao <yao.jin@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) // Lin, Mengdong <mengdong.lin@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) // Add support to read audio firmware topology alongside firmware text. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) // topology data can contain kcontrols, DAPM graphs, widgets, DAIs, DAI links,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) // equalizers, firmware, coefficients etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) // This file only manages the core ALSA and ASoC components, all other bespoke
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) // firmware topology data is passed to component drivers for bespoke handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <sound/soc-dapm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <sound/soc-topology.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SOC_TPLG_MAGIC_BIG_ENDIAN 0x436F5341 /* ASoC in reverse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * We make several passes over the data (since it wont necessarily be ordered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * and process objects in the following order. This guarantees the component
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * drivers will be ready with any vendor data before the mixers and DAPM objects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * are loaded (that may make use of the vendor data).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SOC_TPLG_PASS_MANIFEST 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define SOC_TPLG_PASS_VENDOR 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SOC_TPLG_PASS_MIXER 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SOC_TPLG_PASS_WIDGET 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define SOC_TPLG_PASS_PCM_DAI 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SOC_TPLG_PASS_GRAPH 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SOC_TPLG_PASS_PINS 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SOC_TPLG_PASS_BE_DAI 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SOC_TPLG_PASS_LINK 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SOC_TPLG_PASS_END SOC_TPLG_PASS_LINK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* topology context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct soc_tplg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* runtime FW parsing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const u8 *pos; /* read postion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) const u8 *hdr_pos; /* header position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int pass; /* pass number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* component caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct snd_soc_component *comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 index; /* current block index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u32 req_index; /* required index, only loaded/free matching blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* vendor specific kcontrol operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) const struct snd_soc_tplg_kcontrol_ops *io_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int io_ops_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* vendor specific bytes ext handlers, for TLV bytes controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int bytes_ext_ops_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* optional fw loading callbacks to component drivers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct snd_soc_tplg_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int soc_tplg_process_headers(struct soc_tplg *tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static void soc_tplg_complete(struct soc_tplg *tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static void soc_tplg_denum_remove_texts(struct soc_enum *se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static void soc_tplg_denum_remove_values(struct soc_enum *se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* check we dont overflow the data for this control chunk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) unsigned int count, size_t bytes, const char *elem_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) const u8 *end = tplg->pos + elem_size * count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (end > tplg->fw->data + tplg->fw->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) dev_err(tplg->dev, "ASoC: %s overflow end of data\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) elem_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* check there is enough room in chunk for control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) extra bytes at the end of control are for vendor data here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (elem_size * count > bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) "ASoC: %s count %d of size %zu is bigger than chunk %zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) elem_type, count, elem_size, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static inline int soc_tplg_is_eof(struct soc_tplg *tplg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) const u8 *end = tplg->hdr_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (end >= tplg->fw->data + tplg->fw->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static inline unsigned long soc_tplg_get_hdr_offset(struct soc_tplg *tplg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return (unsigned long)(tplg->hdr_pos - tplg->fw->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static inline unsigned long soc_tplg_get_offset(struct soc_tplg *tplg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return (unsigned long)(tplg->pos - tplg->fw->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* mapping of Kcontrol types and associated operations. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static const struct snd_soc_tplg_kcontrol_ops io_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {SND_SOC_TPLG_CTL_VOLSW, snd_soc_get_volsw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) snd_soc_put_volsw, snd_soc_info_volsw},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {SND_SOC_TPLG_CTL_VOLSW_SX, snd_soc_get_volsw_sx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) snd_soc_put_volsw_sx, NULL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {SND_SOC_TPLG_CTL_ENUM, snd_soc_get_enum_double,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) snd_soc_put_enum_double, snd_soc_info_enum_double},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {SND_SOC_TPLG_CTL_ENUM_VALUE, snd_soc_get_enum_double,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) snd_soc_put_enum_double, NULL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {SND_SOC_TPLG_CTL_BYTES, snd_soc_bytes_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) snd_soc_bytes_put, snd_soc_bytes_info},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {SND_SOC_TPLG_CTL_RANGE, snd_soc_get_volsw_range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) snd_soc_put_volsw_range, snd_soc_info_volsw_range},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {SND_SOC_TPLG_CTL_VOLSW_XR_SX, snd_soc_get_xr_sx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) snd_soc_put_xr_sx, snd_soc_info_xr_sx},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {SND_SOC_TPLG_CTL_STROBE, snd_soc_get_strobe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) snd_soc_put_strobe, NULL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {SND_SOC_TPLG_DAPM_CTL_VOLSW, snd_soc_dapm_get_volsw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) snd_soc_dapm_put_volsw, snd_soc_info_volsw},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE, snd_soc_dapm_get_enum_double,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) snd_soc_dapm_put_enum_double, snd_soc_info_enum_double},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT, snd_soc_dapm_get_enum_double,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) snd_soc_dapm_put_enum_double, NULL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE, snd_soc_dapm_get_enum_double,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) snd_soc_dapm_put_enum_double, NULL},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {SND_SOC_TPLG_DAPM_CTL_PIN, snd_soc_dapm_get_pin_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) snd_soc_dapm_put_pin_switch, snd_soc_dapm_info_pin_switch},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct soc_tplg_map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int kid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* mapping of widget types from UAPI IDs to kernel IDs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static const struct soc_tplg_map dapm_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {SND_SOC_TPLG_DAPM_INPUT, snd_soc_dapm_input},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {SND_SOC_TPLG_DAPM_OUTPUT, snd_soc_dapm_output},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {SND_SOC_TPLG_DAPM_MUX, snd_soc_dapm_mux},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {SND_SOC_TPLG_DAPM_MIXER, snd_soc_dapm_mixer},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {SND_SOC_TPLG_DAPM_PGA, snd_soc_dapm_pga},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {SND_SOC_TPLG_DAPM_OUT_DRV, snd_soc_dapm_out_drv},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {SND_SOC_TPLG_DAPM_ADC, snd_soc_dapm_adc},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {SND_SOC_TPLG_DAPM_DAC, snd_soc_dapm_dac},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {SND_SOC_TPLG_DAPM_SWITCH, snd_soc_dapm_switch},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {SND_SOC_TPLG_DAPM_PRE, snd_soc_dapm_pre},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {SND_SOC_TPLG_DAPM_POST, snd_soc_dapm_post},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {SND_SOC_TPLG_DAPM_AIF_IN, snd_soc_dapm_aif_in},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {SND_SOC_TPLG_DAPM_AIF_OUT, snd_soc_dapm_aif_out},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {SND_SOC_TPLG_DAPM_DAI_IN, snd_soc_dapm_dai_in},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {SND_SOC_TPLG_DAPM_DAI_OUT, snd_soc_dapm_dai_out},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {SND_SOC_TPLG_DAPM_DAI_LINK, snd_soc_dapm_dai_link},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {SND_SOC_TPLG_DAPM_BUFFER, snd_soc_dapm_buffer},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {SND_SOC_TPLG_DAPM_SCHEDULER, snd_soc_dapm_scheduler},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {SND_SOC_TPLG_DAPM_EFFECT, snd_soc_dapm_effect},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {SND_SOC_TPLG_DAPM_SIGGEN, snd_soc_dapm_siggen},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {SND_SOC_TPLG_DAPM_SRC, snd_soc_dapm_src},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {SND_SOC_TPLG_DAPM_ASRC, snd_soc_dapm_asrc},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {SND_SOC_TPLG_DAPM_ENCODER, snd_soc_dapm_encoder},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {SND_SOC_TPLG_DAPM_DECODER, snd_soc_dapm_decoder},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int tplc_chan_get_reg(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct snd_soc_tplg_channel *chan, int map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (le32_to_cpu(chan[i].id) == map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return le32_to_cpu(chan[i].reg);
^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) return -EINVAL;
^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) static int tplc_chan_get_shift(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct snd_soc_tplg_channel *chan, int map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (le32_to_cpu(chan[i].id) == map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return le32_to_cpu(chan[i].shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int get_widget_id(int tplg_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) for (i = 0; i < ARRAY_SIZE(dapm_map); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (tplg_type == dapm_map[i].uid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return dapm_map[i].kid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static inline void soc_bind_err(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct snd_soc_tplg_ctl_hdr *hdr, int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) "ASoC: invalid control type (g,p,i) %d:%d:%d index %d at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) hdr->ops.get, hdr->ops.put, hdr->ops.info, index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) soc_tplg_get_offset(tplg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static inline void soc_control_err(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct snd_soc_tplg_ctl_hdr *hdr, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) "ASoC: no complete mixer IO handler for %s type (g,p,i) %d:%d:%d at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) name, hdr->ops.get, hdr->ops.put, hdr->ops.info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) soc_tplg_get_offset(tplg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /* pass vendor data to component driver for processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static int soc_tplg_vendor_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (tplg->ops && tplg->ops->vendor_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ret = tplg->ops->vendor_load(tplg->comp, tplg->index, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) hdr->vendor_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) "ASoC: vendor load failed at hdr offset %ld/0x%lx for type %d:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) soc_tplg_get_hdr_offset(tplg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) soc_tplg_get_hdr_offset(tplg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) hdr->type, hdr->vendor_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* optionally pass new dynamic widget to component driver. This is mainly for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * external widgets where we can assign private data/ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int soc_tplg_widget_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (tplg->ops && tplg->ops->widget_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return tplg->ops->widget_load(tplg->comp, tplg->index, w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) tplg_w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* optionally pass new dynamic widget to component driver. This is mainly for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * external widgets where we can assign private data/ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static int soc_tplg_widget_ready(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (tplg->ops && tplg->ops->widget_ready)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return tplg->ops->widget_ready(tplg->comp, tplg->index, w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) tplg_w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* pass DAI configurations to component driver for extra initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static int soc_tplg_dai_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct snd_soc_dai_driver *dai_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (tplg->ops && tplg->ops->dai_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return tplg->ops->dai_load(tplg->comp, tplg->index, dai_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) pcm, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* pass link configurations to component driver for extra initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static int soc_tplg_dai_link_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (tplg->ops && tplg->ops->link_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return tplg->ops->link_load(tplg->comp, tplg->index, link, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* tell the component driver that all firmware has been loaded in this request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static void soc_tplg_complete(struct soc_tplg *tplg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (tplg->ops && tplg->ops->complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) tplg->ops->complete(tplg->comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* add a dynamic kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int soc_tplg_add_dcontrol(struct snd_card *card, struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) const struct snd_kcontrol_new *control_new, const char *prefix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) void *data, struct snd_kcontrol **kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) *kcontrol = snd_soc_cnew(control_new, data, control_new->name, prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (*kcontrol == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) dev_err(dev, "ASoC: Failed to create new kcontrol %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) control_new->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) err = snd_ctl_add(card, *kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) dev_err(dev, "ASoC: Failed to add %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) control_new->name, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* add a dynamic kcontrol for component driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int soc_tplg_add_kcontrol(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct snd_kcontrol_new *k, struct snd_kcontrol **kcontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct snd_soc_component *comp = tplg->comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return soc_tplg_add_dcontrol(comp->card->snd_card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) comp->dev, k, comp->name_prefix, comp, kcontrol);
^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) /* remove a mixer kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static void remove_mixer(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct snd_soc_dobj *dobj, int pass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct snd_card *card = comp->card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct soc_mixer_control *sm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) container_of(dobj, struct soc_mixer_control, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) const unsigned int *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (pass != SOC_TPLG_PASS_MIXER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (dobj->ops && dobj->ops->control_unload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) dobj->ops->control_unload(comp, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (dobj->control.kcontrol->tlv.p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) p = dobj->control.kcontrol->tlv.p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) snd_ctl_remove(card, dobj->control.kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) list_del(&dobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) kfree(sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /* remove an enum kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static void remove_enum(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct snd_soc_dobj *dobj, int pass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct snd_card *card = comp->card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct soc_enum *se = container_of(dobj, struct soc_enum, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (pass != SOC_TPLG_PASS_MIXER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (dobj->ops && dobj->ops->control_unload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) dobj->ops->control_unload(comp, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) snd_ctl_remove(card, dobj->control.kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) list_del(&dobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) soc_tplg_denum_remove_values(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) soc_tplg_denum_remove_texts(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) kfree(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* remove a byte kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static void remove_bytes(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct snd_soc_dobj *dobj, int pass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct snd_card *card = comp->card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct soc_bytes_ext *sb =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) container_of(dobj, struct soc_bytes_ext, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (pass != SOC_TPLG_PASS_MIXER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (dobj->ops && dobj->ops->control_unload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dobj->ops->control_unload(comp, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) snd_ctl_remove(card, dobj->control.kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) list_del(&dobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) kfree(sb);
^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) /* remove a route */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static void remove_route(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct snd_soc_dobj *dobj, int pass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct snd_soc_dapm_route *route =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) container_of(dobj, struct snd_soc_dapm_route, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (pass != SOC_TPLG_PASS_GRAPH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (dobj->ops && dobj->ops->dapm_route_unload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dobj->ops->dapm_route_unload(comp, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) list_del(&dobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) kfree(route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* remove a widget and it's kcontrols - routes must be removed first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static void remove_widget(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct snd_soc_dobj *dobj, int pass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct snd_card *card = comp->card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct snd_soc_dapm_widget *w =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) container_of(dobj, struct snd_soc_dapm_widget, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (pass != SOC_TPLG_PASS_WIDGET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (dobj->ops && dobj->ops->widget_unload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) dobj->ops->widget_unload(comp, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (!w->kcontrols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) goto free_news;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * Dynamic Widgets either have 1..N enum kcontrols or mixers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * The enum may either have an array of values or strings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (dobj->widget.kcontrol_type == SND_SOC_TPLG_TYPE_ENUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* enumerated widget mixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct snd_kcontrol *kcontrol = w->kcontrols[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) struct soc_enum *se =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) (struct soc_enum *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) snd_ctl_remove(card, kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* free enum kcontrol's dvalues and dtexts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) soc_tplg_denum_remove_values(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) soc_tplg_denum_remove_texts(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) kfree(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) kfree(w->kcontrol_news[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* volume mixer or bytes controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct snd_kcontrol *kcontrol = w->kcontrols[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (dobj->widget.kcontrol_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) == SND_SOC_TPLG_TYPE_MIXER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) kfree(kcontrol->tlv.p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* Private value is used as struct soc_mixer_control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * for volume mixers or soc_bytes_ext for bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * controls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) kfree((void *)kcontrol->private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) snd_ctl_remove(card, kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) kfree(w->kcontrol_news[i].name);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) free_news:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) kfree(w->kcontrol_news);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) list_del(&dobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* widget w is freed by soc-dapm.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /* remove DAI configurations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static void remove_dai(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct snd_soc_dobj *dobj, int pass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct snd_soc_dai_driver *dai_drv =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) container_of(dobj, struct snd_soc_dai_driver, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct snd_soc_dai *dai, *_dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (pass != SOC_TPLG_PASS_PCM_DAI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (dobj->ops && dobj->ops->dai_unload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) dobj->ops->dai_unload(comp, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) for_each_component_dais_safe(comp, dai, _dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (dai->driver == dai_drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) snd_soc_unregister_dai(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) kfree(dai_drv->playback.stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) kfree(dai_drv->capture.stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) kfree(dai_drv->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) list_del(&dobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) kfree(dai_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) /* remove link configurations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static void remove_link(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct snd_soc_dobj *dobj, int pass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct snd_soc_dai_link *link =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) container_of(dobj, struct snd_soc_dai_link, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (pass != SOC_TPLG_PASS_PCM_DAI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (dobj->ops && dobj->ops->link_unload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) dobj->ops->link_unload(comp, dobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) list_del(&dobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) snd_soc_remove_pcm_runtime(comp->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) snd_soc_get_pcm_runtime(comp->card, link));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) kfree(link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) kfree(link->stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) kfree(link->cpus->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) kfree(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* unload dai link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static void remove_backend_link(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct snd_soc_dobj *dobj, int pass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (pass != SOC_TPLG_PASS_LINK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (dobj->ops && dobj->ops->link_unload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) dobj->ops->link_unload(comp, dobj);
^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) * We don't free the link here as what remove_link() do since BE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * links are not allocated by topology.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * We however need to reset the dobj type to its initial values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) dobj->type = SND_SOC_DOBJ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) list_del(&dobj->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* bind a kcontrol to it's IO handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct snd_kcontrol_new *k,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) const struct soc_tplg *tplg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) const struct snd_soc_tplg_kcontrol_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) const struct snd_soc_tplg_bytes_ext_ops *ext_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) int num_ops, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (le32_to_cpu(hdr->ops.info) == SND_SOC_TPLG_CTL_BYTES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) && (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) || k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct soc_bytes_ext *sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct snd_soc_tplg_bytes_control *be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) sbe = (struct soc_bytes_ext *)k->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) be = container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* TLV bytes controls need standard kcontrol info handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * TLV callback and extended put/get handlers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) k->info = snd_soc_bytes_info_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) k->tlv.c = snd_soc_bytes_tlv_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * When a topology-based implementation abuses the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * control interface and uses bytes_ext controls of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * more than 512 bytes, we need to disable the size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * checks, otherwise accesses to such controls will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * return an -EINVAL error and prevent the card from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * being configured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (IS_ENABLED(CONFIG_SND_CTL_VALIDATION) && sbe->max > 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) k->access |= SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ext_ops = tplg->bytes_ext_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) num_ops = tplg->bytes_ext_ops_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) for (i = 0; i < num_ops; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (!sbe->put &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ext_ops[i].id == le32_to_cpu(be->ext_ops.put))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) sbe->put = ext_ops[i].put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (!sbe->get &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ext_ops[i].id == le32_to_cpu(be->ext_ops.get))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) sbe->get = ext_ops[i].get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) && !sbe->get)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) && !sbe->put)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* try and map vendor specific kcontrol handlers first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ops = tplg->io_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) num_ops = tplg->io_ops_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) for (i = 0; i < num_ops; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) k->put = ops[i].put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) k->get = ops[i].get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) k->info = ops[i].info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /* vendor specific handlers found ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (k->put && k->get && k->info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* none found so try standard kcontrol handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) ops = io_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) num_ops = ARRAY_SIZE(io_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) for (i = 0; i < num_ops; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) k->put = ops[i].put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) k->get = ops[i].get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) k->info = ops[i].info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) /* standard handlers found ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (k->put && k->get && k->info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* nothing to bind */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /* bind a widgets to it's evnt handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) const struct snd_soc_tplg_widget_events *events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) int num_events, u16 event_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) w->event = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) for (i = 0; i < num_events; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (event_type == events[i].type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* found - so assign event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) w->event = events[i].event_handler;
^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) /* not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_bind_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /* optionally pass new dynamic kcontrol to component driver. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static int soc_tplg_init_kcontrol(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct snd_kcontrol_new *k, struct snd_soc_tplg_ctl_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (tplg->ops && tplg->ops->control_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return tplg->ops->control_load(tplg->comp, tplg->index, k,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static int soc_tplg_create_tlv_db_scale(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct snd_kcontrol_new *kc, struct snd_soc_tplg_tlv_dbscale *scale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) unsigned int item_len = 2 * sizeof(unsigned int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) unsigned int *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) p = kzalloc(item_len + 2 * sizeof(unsigned int), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) p[0] = SNDRV_CTL_TLVT_DB_SCALE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) p[1] = item_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) p[2] = le32_to_cpu(scale->min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) p[3] = (le32_to_cpu(scale->step) & TLV_DB_SCALE_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) | (le32_to_cpu(scale->mute) ? TLV_DB_SCALE_MUTE : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) kc->tlv.p = (void *)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static int soc_tplg_create_tlv(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_hdr *tc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct snd_soc_tplg_ctl_tlv *tplg_tlv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) u32 access = le32_to_cpu(tc->access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (!(access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (!(access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) tplg_tlv = &tc->tlv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) switch (le32_to_cpu(tplg_tlv->type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) case SNDRV_CTL_TLVT_DB_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return soc_tplg_create_tlv_db_scale(tplg, kc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) &tplg_tlv->scale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* TODO: add support for other TLV types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) dev_dbg(tplg->dev, "Unsupported TLV type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) tplg_tlv->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static inline void soc_tplg_free_tlv(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct snd_kcontrol_new *kc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) kfree(kc->tlv.p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) struct snd_soc_tplg_bytes_control *be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct soc_bytes_ext *sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct snd_kcontrol_new kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (soc_tplg_check_elem_count(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) sizeof(struct snd_soc_tplg_bytes_control), count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) size, "mixer bytes")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) dev_err(tplg->dev, "ASoC: Invalid count %d for byte control\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) return -EINVAL;
^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) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) be = (struct snd_soc_tplg_bytes_control *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /* validate kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) sbe = kzalloc(sizeof(*sbe), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (sbe == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) le32_to_cpu(be->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) dev_dbg(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) "ASoC: adding bytes kcontrol %s with access 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) be->hdr.name, be->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) memset(&kc, 0, sizeof(kc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) kc.name = be->hdr.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) kc.private_value = (long)sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) kc.access = le32_to_cpu(be->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) sbe->max = le32_to_cpu(be->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) sbe->dobj.type = SND_SOC_DOBJ_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) sbe->dobj.ops = tplg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) INIT_LIST_HEAD(&sbe->dobj.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* map io handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) soc_control_err(tplg, &be->hdr, be->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) kfree(sbe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) /* pass control to driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) err = soc_tplg_init_kcontrol(tplg, &kc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) (struct snd_soc_tplg_ctl_hdr *)be);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) dev_err(tplg->dev, "ASoC: failed to init %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) be->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) kfree(sbe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* register control here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) err = soc_tplg_add_kcontrol(tplg, &kc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) &sbe->dobj.control.kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) dev_err(tplg->dev, "ASoC: failed to add %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) be->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) kfree(sbe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) list_add(&sbe->dobj.list, &tplg->comp->dobj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct snd_soc_tplg_mixer_control *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) struct soc_mixer_control *sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) struct snd_kcontrol_new kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (soc_tplg_check_elem_count(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) sizeof(struct snd_soc_tplg_mixer_control),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) count, size, "mixers")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) dev_err(tplg->dev, "ASoC: invalid count %d for controls\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) mc = (struct snd_soc_tplg_mixer_control *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) /* validate kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) sm = kzalloc(sizeof(*sm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (sm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) le32_to_cpu(mc->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) dev_dbg(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) "ASoC: adding mixer kcontrol %s with access 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) mc->hdr.name, mc->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) memset(&kc, 0, sizeof(kc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) kc.name = mc->hdr.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) kc.private_value = (long)sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) kc.access = le32_to_cpu(mc->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /* we only support FL/FR channel mapping atm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) sm->reg = tplc_chan_get_reg(tplg, mc->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) sm->rreg = tplc_chan_get_reg(tplg, mc->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) SNDRV_CHMAP_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) sm->shift = tplc_chan_get_shift(tplg, mc->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) sm->rshift = tplc_chan_get_shift(tplg, mc->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) SNDRV_CHMAP_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) sm->max = le32_to_cpu(mc->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) sm->min = le32_to_cpu(mc->min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) sm->invert = le32_to_cpu(mc->invert);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) sm->platform_max = le32_to_cpu(mc->platform_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) sm->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) sm->dobj.ops = tplg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) sm->dobj.type = SND_SOC_DOBJ_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) INIT_LIST_HEAD(&sm->dobj.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) /* map io handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) soc_control_err(tplg, &mc->hdr, mc->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) kfree(sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* create any TLV data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) err = soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) mc->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) kfree(sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* pass control to driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) err = soc_tplg_init_kcontrol(tplg, &kc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) (struct snd_soc_tplg_ctl_hdr *) mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) dev_err(tplg->dev, "ASoC: failed to init %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) mc->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) soc_tplg_free_tlv(tplg, &kc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) kfree(sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) /* register control here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) err = soc_tplg_add_kcontrol(tplg, &kc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) &sm->dobj.control.kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) dev_err(tplg->dev, "ASoC: failed to add %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) mc->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) soc_tplg_free_tlv(tplg, &kc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) kfree(sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) list_add(&sm->dobj.list, &tplg->comp->dobj_list);
^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) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static int soc_tplg_denum_create_texts(struct soc_enum *se,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct snd_soc_tplg_enum_control *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) se->dobj.control.dtexts =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) kcalloc(le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (se->dobj.control.dtexts == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) for (i = 0; i < le32_to_cpu(ec->items); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) goto err;
^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) se->dobj.control.dtexts[i] = kstrdup(ec->texts[i], GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (!se->dobj.control.dtexts[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) se->items = le32_to_cpu(ec->items);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) se->texts = (const char * const *)se->dobj.control.dtexts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) se->items = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) soc_tplg_denum_remove_texts(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static inline void soc_tplg_denum_remove_texts(struct soc_enum *se)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) int i = se->items;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) for (--i; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) kfree(se->dobj.control.dtexts[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) kfree(se->dobj.control.dtexts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static int soc_tplg_denum_create_values(struct soc_enum *se,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) struct snd_soc_tplg_enum_control *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (le32_to_cpu(ec->items) > sizeof(*ec->values))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) se->dobj.control.dvalues = kzalloc(le32_to_cpu(ec->items) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) sizeof(*se->dobj.control.dvalues),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (!se->dobj.control.dvalues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) /* convert from little-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) for (i = 0; i < le32_to_cpu(ec->items); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) static inline void soc_tplg_denum_remove_values(struct soc_enum *se)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) kfree(se->dobj.control.dvalues);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct snd_soc_tplg_enum_control *ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) struct soc_enum *se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) struct snd_kcontrol_new kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (soc_tplg_check_elem_count(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) sizeof(struct snd_soc_tplg_enum_control),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) count, size, "enums")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) dev_err(tplg->dev, "ASoC: invalid count %d for enum controls\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) ec = (struct snd_soc_tplg_enum_control *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* validate kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) se = kzalloc((sizeof(*se)), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (se == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) le32_to_cpu(ec->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) ec->hdr.name, ec->items);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) memset(&kc, 0, sizeof(kc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) kc.name = ec->hdr.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) kc.private_value = (long)se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) kc.access = le32_to_cpu(ec->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) se->shift_l = tplc_chan_get_shift(tplg, ec->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) se->shift_r = tplc_chan_get_shift(tplg, ec->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) se->mask = le32_to_cpu(ec->mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) se->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) se->dobj.type = SND_SOC_DOBJ_ENUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) se->dobj.ops = tplg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) INIT_LIST_HEAD(&se->dobj.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) switch (le32_to_cpu(ec->hdr.ops.info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) case SND_SOC_TPLG_CTL_ENUM_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) err = soc_tplg_denum_create_values(se, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) "ASoC: could not create values for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) goto err_denum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) case SND_SOC_TPLG_CTL_ENUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) err = soc_tplg_denum_create_texts(se, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) "ASoC: could not create texts for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) goto err_denum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) "ASoC: invalid enum control type %d for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) ec->hdr.ops.info, ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) goto err_denum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) /* map io handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) soc_control_err(tplg, &ec->hdr, ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) goto err_denum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) /* pass control to driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) err = soc_tplg_init_kcontrol(tplg, &kc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) (struct snd_soc_tplg_ctl_hdr *) ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) dev_err(tplg->dev, "ASoC: failed to init %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) goto err_denum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) /* register control here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) err = soc_tplg_add_kcontrol(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) &kc, &se->dobj.control.kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) goto err_denum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) list_add(&se->dobj.list, &tplg->comp->dobj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) err_denum:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) kfree(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) struct snd_soc_tplg_ctl_hdr *control_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) soc_tplg_get_offset(tplg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) for (i = 0; i < le32_to_cpu(hdr->count); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) dev_err(tplg->dev, "ASoC: invalid control size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) switch (le32_to_cpu(control_hdr->ops.info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) case SND_SOC_TPLG_CTL_VOLSW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) case SND_SOC_TPLG_CTL_STROBE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) case SND_SOC_TPLG_CTL_VOLSW_SX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) case SND_SOC_TPLG_CTL_RANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) case SND_SOC_TPLG_DAPM_CTL_VOLSW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) case SND_SOC_TPLG_DAPM_CTL_PIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) ret = soc_tplg_dmixer_create(tplg, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) le32_to_cpu(hdr->payload_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) case SND_SOC_TPLG_CTL_ENUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) case SND_SOC_TPLG_CTL_ENUM_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) ret = soc_tplg_denum_create(tplg, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) le32_to_cpu(hdr->payload_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) case SND_SOC_TPLG_CTL_BYTES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) ret = soc_tplg_dbytes_create(tplg, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) le32_to_cpu(hdr->payload_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) soc_bind_err(tplg, control_hdr, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) dev_err(tplg->dev, "ASoC: invalid control\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return ret;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) /* optionally pass new dynamic kcontrol to component driver. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) static int soc_tplg_add_route(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) struct snd_soc_dapm_route *route)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (tplg->ops && tplg->ops->dapm_route_load)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) return tplg->ops->dapm_route_load(tplg->comp, tplg->index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) struct snd_soc_tplg_dapm_graph_elem *elem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) struct snd_soc_dapm_route **routes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) int count, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) count = le32_to_cpu(hdr->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (soc_tplg_check_elem_count(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) sizeof(struct snd_soc_tplg_dapm_graph_elem),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) count, le32_to_cpu(hdr->payload_size), "graph")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) dev_err(tplg->dev, "ASoC: invalid count %d for DAPM routes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes for index %d\n", count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) hdr->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) /* allocate memory for pointer to array of dapm routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) routes = kcalloc(count, sizeof(struct snd_soc_dapm_route *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (!routes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * allocate memory for each dapm route in the array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) * This needs to be done individually so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * each route can be freed when it is removed in remove_route().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) routes[i] = kzalloc(sizeof(*routes[i]), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (!routes[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /* free previously allocated memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) for (j = 0; j < i; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) kfree(routes[j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) kfree(routes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) /* validate routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) routes[i]->source = elem->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) routes[i]->sink = elem->sink;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) /* set to NULL atm for tplg users */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) routes[i]->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) routes[i]->control = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) routes[i]->control = elem->control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) /* add route dobj to dobj_list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) routes[i]->dobj.type = SND_SOC_DOBJ_GRAPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) routes[i]->dobj.ops = tplg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) routes[i]->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) ret = soc_tplg_add_route(tplg, routes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) * this route was added to the list, it will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) * be freed in remove_route() so increment the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) * counter to skip it in the error handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) /* add route, but keep going if some fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) snd_soc_dapm_add_routes(dapm, routes[i], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) * free memory allocated for all dapm routes not added to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) * list in case of error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) while (i < count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) kfree(routes[i++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^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) * free pointer to array of dapm routes as this is no longer needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) * The memory allocated for each dapm route will be freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) * when it is removed in remove_route().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) kfree(routes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) struct soc_tplg *tplg, int num_kcontrols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) struct snd_kcontrol_new *kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) struct soc_mixer_control *sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) struct snd_soc_tplg_mixer_control *mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (kc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) for (i = 0; i < num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) mc = (struct snd_soc_tplg_mixer_control *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) /* validate kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) goto err_sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) sm = kzalloc(sizeof(*sm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (sm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) goto err_sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) le32_to_cpu(mc->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) dev_dbg(tplg->dev, " adding DAPM widget mixer control %s at %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) mc->hdr.name, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) kc[i].private_value = (long)sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) kc[i].name = kstrdup(mc->hdr.name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (kc[i].name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) goto err_sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) kc[i].access = le32_to_cpu(mc->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) /* we only support FL/FR channel mapping atm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) sm->reg = tplc_chan_get_reg(tplg, mc->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) sm->rreg = tplc_chan_get_reg(tplg, mc->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) SNDRV_CHMAP_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) sm->shift = tplc_chan_get_shift(tplg, mc->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) sm->rshift = tplc_chan_get_shift(tplg, mc->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) SNDRV_CHMAP_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) sm->max = le32_to_cpu(mc->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) sm->min = le32_to_cpu(mc->min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) sm->invert = le32_to_cpu(mc->invert);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) sm->platform_max = le32_to_cpu(mc->platform_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) sm->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) INIT_LIST_HEAD(&sm->dobj.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) /* map io handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) soc_control_err(tplg, &mc->hdr, mc->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) goto err_sm;
^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) /* create any TLV data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) err = soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) mc->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) goto err_sm;
^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) /* pass control to driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) err = soc_tplg_init_kcontrol(tplg, &kc[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) (struct snd_soc_tplg_ctl_hdr *)mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) dev_err(tplg->dev, "ASoC: failed to init %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) mc->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) goto err_sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) return kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) err_sm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) for (; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) soc_tplg_free_tlv(tplg, &kc[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) sm = (struct soc_mixer_control *)kc[i].private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) kfree(sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) kfree(kc[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) kfree(kc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) return NULL;
^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) static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) struct soc_tplg *tplg, int num_kcontrols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) struct snd_kcontrol_new *kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) struct snd_soc_tplg_enum_control *ec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) struct soc_enum *se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) if (kc == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) for (i = 0; i < num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) ec = (struct snd_soc_tplg_enum_control *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) /* validate kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) goto err_se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) se = kzalloc(sizeof(*se), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (se == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) goto err_se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) le32_to_cpu(ec->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) kc[i].private_value = (long)se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) if (kc[i].name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) goto err_se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) kc[i].access = le32_to_cpu(ec->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /* we only support FL/FR channel mapping atm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) se->shift_l = tplc_chan_get_shift(tplg, ec->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) SNDRV_CHMAP_FL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) se->shift_r = tplc_chan_get_shift(tplg, ec->channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) SNDRV_CHMAP_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) se->items = le32_to_cpu(ec->items);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) se->mask = le32_to_cpu(ec->mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) se->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) switch (le32_to_cpu(ec->hdr.ops.info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) case SND_SOC_TPLG_CTL_ENUM_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) err = soc_tplg_denum_create_values(se, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) dev_err(tplg->dev, "ASoC: could not create values for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) goto err_se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) case SND_SOC_TPLG_CTL_ENUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) err = soc_tplg_denum_create_texts(se, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) dev_err(tplg->dev, "ASoC: could not create texts for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) goto err_se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) ec->hdr.ops.info, ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) goto err_se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) /* map io handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc[i], tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) soc_control_err(tplg, &ec->hdr, ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) goto err_se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) /* pass control to driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) err = soc_tplg_init_kcontrol(tplg, &kc[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) (struct snd_soc_tplg_ctl_hdr *)ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) dev_err(tplg->dev, "ASoC: failed to init %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) ec->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) goto err_se;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) return kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) err_se:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) for (; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) /* free values and texts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) se = (struct soc_enum *)kc[i].private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) if (se) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) soc_tplg_denum_remove_values(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) soc_tplg_denum_remove_texts(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) kfree(se);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) kfree(kc[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) kfree(kc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) struct soc_tplg *tplg, int num_kcontrols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) struct snd_soc_tplg_bytes_control *be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) struct soc_bytes_ext *sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) struct snd_kcontrol_new *kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (!kc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) for (i = 0; i < num_kcontrols; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) be = (struct snd_soc_tplg_bytes_control *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) /* validate kcontrol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) goto err_sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) sbe = kzalloc(sizeof(*sbe), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) if (sbe == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) goto err_sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) le32_to_cpu(be->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) dev_dbg(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) "ASoC: adding bytes kcontrol %s with access 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) be->hdr.name, be->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) kc[i].private_value = (long)sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) if (kc[i].name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) goto err_sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) kc[i].access = le32_to_cpu(be->hdr.access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) sbe->max = le32_to_cpu(be->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) INIT_LIST_HEAD(&sbe->dobj.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) /* map standard io handlers and check for external handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) soc_control_err(tplg, &be->hdr, be->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) goto err_sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) /* pass control to driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) err = soc_tplg_init_kcontrol(tplg, &kc[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) (struct snd_soc_tplg_ctl_hdr *)be);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) dev_err(tplg->dev, "ASoC: failed to init %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) be->hdr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) goto err_sbe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) return kc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) err_sbe:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) for (; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) sbe = (struct soc_bytes_ext *)kc[i].private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) kfree(sbe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) kfree(kc[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) kfree(kc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) struct snd_soc_tplg_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) struct snd_soc_dapm_widget template, *widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) struct snd_soc_tplg_ctl_hdr *control_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) struct snd_soc_card *card = tplg->comp->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) unsigned int kcontrol_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) w->name, w->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) memset(&template, 0, sizeof(template));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) /* map user to kernel widget ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) template.id = get_widget_id(le32_to_cpu(w->id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) if ((int)template.id < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) return template.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) /* strings are allocated here, but used and freed by the widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) template.name = kstrdup(w->name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) if (!template.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) template.sname = kstrdup(w->sname, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (!template.sname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) template.reg = le32_to_cpu(w->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) template.shift = le32_to_cpu(w->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) template.mask = le32_to_cpu(w->mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) template.subseq = le32_to_cpu(w->subseq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) template.on_val = w->invert ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) template.off_val = w->invert ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) template.ignore_suspend = le32_to_cpu(w->ignore_suspend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) template.event_flags = le16_to_cpu(w->event_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) template.dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) tplg->pos +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) (sizeof(struct snd_soc_tplg_dapm_widget) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) le32_to_cpu(w->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (w->num_kcontrols == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) kcontrol_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) template.num_kcontrols = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) goto widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) dev_dbg(tplg->dev, "ASoC: template %s has %d controls of type %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) w->name, w->num_kcontrols, control_hdr->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) switch (le32_to_cpu(control_hdr->ops.info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) case SND_SOC_TPLG_CTL_VOLSW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) case SND_SOC_TPLG_CTL_STROBE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) case SND_SOC_TPLG_CTL_VOLSW_SX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) case SND_SOC_TPLG_CTL_RANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) case SND_SOC_TPLG_DAPM_CTL_VOLSW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) kcontrol_type = SND_SOC_TPLG_TYPE_MIXER; /* volume mixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) template.kcontrol_news =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) soc_tplg_dapm_widget_dmixer_create(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) template.num_kcontrols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) if (!template.kcontrol_news) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) goto hdr_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) case SND_SOC_TPLG_CTL_ENUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) case SND_SOC_TPLG_CTL_ENUM_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) kcontrol_type = SND_SOC_TPLG_TYPE_ENUM; /* enumerated mixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) template.kcontrol_news =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) soc_tplg_dapm_widget_denum_create(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) template.num_kcontrols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) if (!template.kcontrol_news) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) goto hdr_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) case SND_SOC_TPLG_CTL_BYTES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) kcontrol_type = SND_SOC_TPLG_TYPE_BYTES; /* bytes control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) template.kcontrol_news =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) soc_tplg_dapm_widget_dbytes_create(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) template.num_kcontrols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (!template.kcontrol_news) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) goto hdr_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) control_hdr->ops.get, control_hdr->ops.put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) le32_to_cpu(control_hdr->ops.info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) goto hdr_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) widget:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) ret = soc_tplg_widget_load(tplg, &template, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) goto hdr_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) /* card dapm mutex is held by the core if we are loading topology
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) * data during sound card init. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) if (card->instantiated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) widget = snd_soc_dapm_new_control(dapm, &template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) widget = snd_soc_dapm_new_control_unlocked(dapm, &template);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) if (IS_ERR(widget)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) ret = PTR_ERR(widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) goto hdr_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) widget->dobj.type = SND_SOC_DOBJ_WIDGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) widget->dobj.widget.kcontrol_type = kcontrol_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) widget->dobj.ops = tplg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) widget->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) list_add(&widget->dobj.list, &tplg->comp->dobj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) ret = soc_tplg_widget_ready(tplg, widget, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) goto ready_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) kfree(template.sname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) kfree(template.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) ready_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) snd_soc_tplg_widget_remove(widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) snd_soc_dapm_free_widget(widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) hdr_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) kfree(template.sname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) kfree(template.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) struct snd_soc_tplg_dapm_widget *widget;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) int ret, count, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) count = le32_to_cpu(hdr->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) if (le32_to_cpu(widget->size) != sizeof(*widget)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) dev_err(tplg->dev, "ASoC: invalid widget size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) ret = soc_tplg_dapm_widget_create(tplg, widget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) dev_err(tplg->dev, "ASoC: failed to load widget %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) widget->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) struct snd_soc_card *card = tplg->comp->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) /* Card might not have been registered at this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) * If so, just return success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (!card || !card->instantiated) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) dev_warn(tplg->dev, "ASoC: Parent card not yet available,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) " widget card binding deferred\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) ret = snd_soc_dapm_new_widgets(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) static int set_stream_info(struct snd_soc_pcm_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) struct snd_soc_tplg_stream_caps *caps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) stream->stream_name = kstrdup(caps->name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (!stream->stream_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) stream->channels_min = le32_to_cpu(caps->channels_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) stream->channels_max = le32_to_cpu(caps->channels_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) stream->rates = le32_to_cpu(caps->rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) stream->rate_min = le32_to_cpu(caps->rate_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) stream->rate_max = le32_to_cpu(caps->rate_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) stream->formats = le64_to_cpu(caps->formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) stream->sig_bits = le32_to_cpu(caps->sig_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) unsigned int flag_mask, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) dai_drv->symmetric_rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) dai_drv->symmetric_channels =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) dai_drv->symmetric_samplebits =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) static int soc_tplg_dai_create(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) struct snd_soc_tplg_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) struct snd_soc_dai_driver *dai_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) struct snd_soc_pcm_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) struct snd_soc_tplg_stream_caps *caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) struct snd_soc_dapm_context *dapm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) snd_soc_component_get_dapm(tplg->comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) dai_drv = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (dai_drv == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) if (strlen(pcm->dai_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) if (!dai_drv->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) dai_drv->id = le32_to_cpu(pcm->dai_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) if (pcm->playback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) stream = &dai_drv->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) ret = set_stream_info(stream, caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) if (pcm->capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) stream = &dai_drv->capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) ret = set_stream_info(stream, caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) goto err;
^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) if (pcm->compress)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) dai_drv->compress_new = snd_soc_new_compress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) /* pass control to component driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) dai_drv->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) dai_drv->dobj.ops = tplg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) dai_drv->dobj.type = SND_SOC_DOBJ_PCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) /* register the DAI to the component */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) dai = snd_soc_register_dai(tplg->comp, dai_drv, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) if (!dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) /* Create the DAI widgets here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) snd_soc_unregister_dai(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) kfree(dai_drv->playback.stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) kfree(dai_drv->capture.stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) kfree(dai_drv->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) kfree(dai_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) static void set_link_flags(struct snd_soc_dai_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) unsigned int flag_mask, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) link->symmetric_rates =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) link->symmetric_channels =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) link->symmetric_samplebits =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) link->ignore_suspend =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) flags & SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) /* create the FE DAI link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) struct snd_soc_tplg_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) struct snd_soc_dai_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) struct snd_soc_dai_link_component *dlc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) /* link + cpu + codec + platform */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) link = kzalloc(sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) if (link == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) dlc = (struct snd_soc_dai_link_component *)(link + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) link->cpus = &dlc[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) link->codecs = &dlc[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) link->platforms = &dlc[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) link->num_cpus = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) link->num_codecs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) link->num_platforms = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) link->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) link->dobj.ops = tplg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) if (strlen(pcm->pcm_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) link->name = kstrdup(pcm->pcm_name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) if (!link->name || !link->stream_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) link->id = le32_to_cpu(pcm->pcm_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) if (strlen(pcm->dai_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) if (!link->cpus->dai_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) link->codecs->name = "snd-soc-dummy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) link->codecs->dai_name = "snd-soc-dummy-dai";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) link->platforms->name = "snd-soc-dummy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) /* enable DPCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) link->dynamic = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) link->dpcm_playback = le32_to_cpu(pcm->playback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) link->dpcm_capture = le32_to_cpu(pcm->capture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (pcm->flag_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) set_link_flags(link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) le32_to_cpu(pcm->flag_mask),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) le32_to_cpu(pcm->flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) /* pass control to component driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) ret = soc_tplg_dai_link_load(tplg, link, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) ret = snd_soc_add_pcm_runtime(tplg->comp->card, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) dev_err(tplg->comp->dev, "ASoC: adding FE link failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) list_add(&link->dobj.list, &tplg->comp->dobj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) kfree(link->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) kfree(link->stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) kfree(link->cpus->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) kfree(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) /* create a FE DAI and DAI link from the PCM object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) static int soc_tplg_pcm_create(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) struct snd_soc_tplg_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) ret = soc_tplg_dai_create(tplg, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) return soc_tplg_fe_link_create(tplg, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) /* copy stream caps from the old version 4 of source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) static void stream_caps_new_ver(struct snd_soc_tplg_stream_caps *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) struct snd_soc_tplg_stream_caps_v4 *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) dest->size = cpu_to_le32(sizeof(*dest));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) memcpy(dest->name, src->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) dest->formats = src->formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) dest->rates = src->rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) dest->rate_min = src->rate_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) dest->rate_max = src->rate_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) dest->channels_min = src->channels_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) dest->channels_max = src->channels_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) dest->periods_min = src->periods_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) dest->periods_max = src->periods_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) dest->period_size_min = src->period_size_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) dest->period_size_max = src->period_size_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) dest->buffer_size_min = src->buffer_size_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) dest->buffer_size_max = src->buffer_size_max;
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) * pcm_new_ver - Create the new version of PCM from the old version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) * @tplg: topology context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) * @src: older version of pcm as a source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) * @pcm: latest version of pcm created from the source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) * Support from vesion 4. User should free the returned pcm manually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) static int pcm_new_ver(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) struct snd_soc_tplg_pcm *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) struct snd_soc_tplg_pcm **pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) struct snd_soc_tplg_pcm *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) struct snd_soc_tplg_pcm_v4 *src_v4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) *pcm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) if (le32_to_cpu(src->size) != sizeof(*src_v4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) dev_err(tplg->dev, "ASoC: invalid PCM size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) dev_warn(tplg->dev, "ASoC: old version of PCM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) src_v4 = (struct snd_soc_tplg_pcm_v4 *)src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) dest = kzalloc(sizeof(*dest), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) if (!dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) memcpy(dest->pcm_name, src_v4->pcm_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) memcpy(dest->dai_name, src_v4->dai_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) dest->pcm_id = src_v4->pcm_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) dest->dai_id = src_v4->dai_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) dest->playback = src_v4->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) dest->capture = src_v4->capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) dest->compress = src_v4->compress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) dest->num_streams = src_v4->num_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) for (i = 0; i < le32_to_cpu(dest->num_streams); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) memcpy(&dest->stream[i], &src_v4->stream[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) sizeof(struct snd_soc_tplg_stream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) stream_caps_new_ver(&dest->caps[i], &src_v4->caps[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) *pcm = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) struct snd_soc_tplg_pcm *pcm, *_pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) bool abi_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) count = le32_to_cpu(hdr->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) /* check the element size and count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) size = le32_to_cpu(pcm->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) if (size > sizeof(struct snd_soc_tplg_pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) || size < sizeof(struct snd_soc_tplg_pcm_v4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) dev_err(tplg->dev, "ASoC: invalid size %d for PCM elems\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) if (soc_tplg_check_elem_count(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) size, count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) le32_to_cpu(hdr->payload_size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) "PCM DAI")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) dev_err(tplg->dev, "ASoC: invalid count %d for PCM DAI elems\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) size = le32_to_cpu(pcm->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) /* check ABI version by size, create a new version of pcm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) * if abi not match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) if (size == sizeof(*pcm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) abi_match = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) _pcm = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) abi_match = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) ret = pcm_new_ver(tplg, pcm, &_pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) /* create the FE DAIs and DAI links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) ret = soc_tplg_pcm_create(tplg, _pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) if (!abi_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) kfree(_pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) /* offset by version-specific struct size and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) * real priv data size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) tplg->pos += size + le32_to_cpu(_pcm->priv.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) if (!abi_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) kfree(_pcm); /* free the duplicated one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) * set_link_hw_format - Set the HW audio format of the physical DAI link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) * @link: &snd_soc_dai_link which should be updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) * @cfg: physical link configs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) * Topology context contains a list of supported HW formats (configs) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) * a default format ID for the physical link. This function will use this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) * default ID to choose the HW format to set the link's DAI format for init.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) static void set_link_hw_format(struct snd_soc_dai_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) struct snd_soc_tplg_link_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) struct snd_soc_tplg_hw_config *hw_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) unsigned char bclk_master, fsync_master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) unsigned char invert_bclk, invert_fsync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) for (i = 0; i < le32_to_cpu(cfg->num_hw_configs); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) hw_config = &cfg->hw_config[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) if (hw_config->id != cfg->default_hw_config_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) link->dai_fmt = le32_to_cpu(hw_config->fmt) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) SND_SOC_DAIFMT_FORMAT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) /* clock gating */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) switch (hw_config->clock_gated) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) case SND_SOC_TPLG_DAI_CLK_GATE_GATED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) link->dai_fmt |= SND_SOC_DAIFMT_GATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) case SND_SOC_TPLG_DAI_CLK_GATE_CONT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) link->dai_fmt |= SND_SOC_DAIFMT_CONT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) /* ignore the value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) /* clock signal polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) invert_bclk = hw_config->invert_bclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) invert_fsync = hw_config->invert_fsync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) if (!invert_bclk && !invert_fsync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) link->dai_fmt |= SND_SOC_DAIFMT_NB_NF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) else if (!invert_bclk && invert_fsync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) link->dai_fmt |= SND_SOC_DAIFMT_NB_IF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) else if (invert_bclk && !invert_fsync)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) link->dai_fmt |= SND_SOC_DAIFMT_IB_NF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) link->dai_fmt |= SND_SOC_DAIFMT_IB_IF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) /* clock masters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) bclk_master = (hw_config->bclk_master ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) SND_SOC_TPLG_BCLK_CM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) fsync_master = (hw_config->fsync_master ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) SND_SOC_TPLG_FSYNC_CM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) if (bclk_master && fsync_master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) else if (!bclk_master && fsync_master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) else if (bclk_master && !fsync_master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) * link_new_ver - Create a new physical link config from the old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) * version of source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) * @tplg: topology context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) * @src: old version of phyical link config as a source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) * @link: latest version of physical link config created from the source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) * Support from vesion 4. User need free the returned link config manually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) static int link_new_ver(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) struct snd_soc_tplg_link_config *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) struct snd_soc_tplg_link_config **link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) struct snd_soc_tplg_link_config *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) struct snd_soc_tplg_link_config_v4 *src_v4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) *link = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) if (le32_to_cpu(src->size) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) sizeof(struct snd_soc_tplg_link_config_v4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) dev_err(tplg->dev, "ASoC: invalid physical link config size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) dev_warn(tplg->dev, "ASoC: old version of physical link config\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) src_v4 = (struct snd_soc_tplg_link_config_v4 *)src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) dest = kzalloc(sizeof(*dest), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) if (!dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) dest->size = cpu_to_le32(sizeof(*dest));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) dest->id = src_v4->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) dest->num_streams = src_v4->num_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) for (i = 0; i < le32_to_cpu(dest->num_streams); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) memcpy(&dest->stream[i], &src_v4->stream[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) sizeof(struct snd_soc_tplg_stream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) *link = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) * snd_soc_find_dai_link - Find a DAI link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) * @card: soc card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) * @id: DAI link ID to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) * @name: DAI link name to match, optional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) * @stream_name: DAI link stream name to match, optional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) * This function will search all existing DAI links of the soc card to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) * find the link of the same ID. Since DAI links may not have their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) * unique ID, so name and stream name should also match if being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) * specified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) * Return: pointer of DAI link, or NULL if not found.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) static struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) int id, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) const char *stream_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) struct snd_soc_pcm_runtime *rtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) struct snd_soc_dai_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) for_each_card_rtds(card, rtd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) link = rtd->dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) if (link->id != id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) if (name && (!link->name || strcmp(name, link->name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) if (stream_name && (!link->stream_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) || strcmp(stream_name, link->stream_name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) return link;
^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) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) /* Find and configure an existing physical DAI link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) static int soc_tplg_link_config(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) struct snd_soc_tplg_link_config *cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) struct snd_soc_dai_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) const char *name, *stream_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) len = strnlen(cfg->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) if (len == SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) else if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) name = cfg->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) len = strnlen(cfg->stream_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) if (len == SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) else if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) stream_name = cfg->stream_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) stream_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) link = snd_soc_find_dai_link(tplg->comp->card, le32_to_cpu(cfg->id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) name, stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) if (!link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) dev_err(tplg->dev, "ASoC: physical link %s (id %d) not exist\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) name, cfg->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) /* hw format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) if (cfg->num_hw_configs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) set_link_hw_format(link, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) /* flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) if (cfg->flag_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) set_link_flags(link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) le32_to_cpu(cfg->flag_mask),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) le32_to_cpu(cfg->flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) /* pass control to component driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) ret = soc_tplg_dai_link_load(tplg, link, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) dev_err(tplg->dev, "ASoC: physical link loading failed\n");
^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) /* for unloading it in snd_soc_tplg_component_remove */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) link->dobj.index = tplg->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) link->dobj.ops = tplg->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) list_add(&link->dobj.list, &tplg->comp->dobj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) /* Load physical link config elements from the topology context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) static int soc_tplg_link_elems_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) struct snd_soc_tplg_link_config *link, *_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) bool abi_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) count = le32_to_cpu(hdr->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) /* check the element size and count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) link = (struct snd_soc_tplg_link_config *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) size = le32_to_cpu(link->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) if (size > sizeof(struct snd_soc_tplg_link_config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) || size < sizeof(struct snd_soc_tplg_link_config_v4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) dev_err(tplg->dev, "ASoC: invalid size %d for physical link elems\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) if (soc_tplg_check_elem_count(tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) size, count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) le32_to_cpu(hdr->payload_size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) "physical link config")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) dev_err(tplg->dev, "ASoC: invalid count %d for physical link elems\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) /* config physical DAI links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) link = (struct snd_soc_tplg_link_config *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) size = le32_to_cpu(link->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) if (size == sizeof(*link)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) abi_match = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) _link = link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) abi_match = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) ret = link_new_ver(tplg, link, &_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) ret = soc_tplg_link_config(tplg, _link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) if (!abi_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) kfree(_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) /* offset by version-specific struct size and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) * real priv data size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) tplg->pos += size + le32_to_cpu(_link->priv.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) if (!abi_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) kfree(_link); /* free the duplicated one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) * soc_tplg_dai_config - Find and configure an existing physical DAI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) * @tplg: topology context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) * @d: physical DAI configs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) * The physical dai should already be registered by the platform driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) * The platform driver should specify the DAI name and ID for matching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) static int soc_tplg_dai_config(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) struct snd_soc_tplg_dai *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) struct snd_soc_dai_link_component dai_component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) struct snd_soc_dai_driver *dai_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) struct snd_soc_pcm_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) struct snd_soc_tplg_stream_caps *caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) memset(&dai_component, 0, sizeof(dai_component));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) dai_component.dai_name = d->dai_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) dai = snd_soc_find_dai(&dai_component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) if (!dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) dev_err(tplg->dev, "ASoC: physical DAI %s not registered\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) d->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) if (le32_to_cpu(d->dai_id) != dai->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) dev_err(tplg->dev, "ASoC: physical DAI %s id mismatch\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) d->dai_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) dai_drv = dai->driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) if (!dai_drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) if (d->playback) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) stream = &dai_drv->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) ret = set_stream_info(stream, caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) if (d->capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) stream = &dai_drv->capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) ret = set_stream_info(stream, caps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) if (d->flag_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) set_dai_flags(dai_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) le32_to_cpu(d->flag_mask),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) le32_to_cpu(d->flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) /* pass control to component driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) kfree(dai_drv->playback.stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) kfree(dai_drv->capture.stream_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) /* load physical DAI elements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) struct snd_soc_tplg_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) count = le32_to_cpu(hdr->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) /* config the existing BE DAIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) dai = (struct snd_soc_tplg_dai *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) if (le32_to_cpu(dai->size) != sizeof(*dai)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) dev_err(tplg->dev, "ASoC: invalid physical DAI size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) ret = soc_tplg_dai_config(tplg, dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) dev_err(tplg->dev, "ASoC: failed to configure DAI\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) * manifest_new_ver - Create a new version of manifest from the old version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) * of source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) * @tplg: topology context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) * @src: old version of manifest as a source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) * @manifest: latest version of manifest created from the source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) * Support from vesion 4. Users need free the returned manifest manually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) static int manifest_new_ver(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) struct snd_soc_tplg_manifest *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) struct snd_soc_tplg_manifest **manifest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) struct snd_soc_tplg_manifest *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) struct snd_soc_tplg_manifest_v4 *src_v4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) *manifest = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) size = le32_to_cpu(src->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) if (size != sizeof(*src_v4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) dev_warn(tplg->dev, "ASoC: invalid manifest size %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) if (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) src->size = cpu_to_le32(sizeof(*src_v4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) dev_warn(tplg->dev, "ASoC: old version of manifest\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) src_v4 = (struct snd_soc_tplg_manifest_v4 *)src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) dest = kzalloc(sizeof(*dest) + le32_to_cpu(src_v4->priv.size),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) if (!dest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) dest->control_elems = src_v4->control_elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) dest->widget_elems = src_v4->widget_elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) dest->graph_elems = src_v4->graph_elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) dest->pcm_elems = src_v4->pcm_elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) dest->dai_link_elems = src_v4->dai_link_elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) dest->priv.size = src_v4->priv.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) if (dest->priv.size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) memcpy(dest->priv.data, src_v4->priv.data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) le32_to_cpu(src_v4->priv.size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) *manifest = dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) static int soc_tplg_manifest_load(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) struct snd_soc_tplg_manifest *manifest, *_manifest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) bool abi_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) manifest = (struct snd_soc_tplg_manifest *)tplg->pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) /* check ABI version by size, create a new manifest if abi not match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) if (le32_to_cpu(manifest->size) == sizeof(*manifest)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) abi_match = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) _manifest = manifest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) abi_match = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) ret = manifest_new_ver(tplg, manifest, &_manifest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) /* pass control to component driver for optional further init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) if (tplg->ops && tplg->ops->manifest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) ret = tplg->ops->manifest(tplg->comp, tplg->index, _manifest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) if (!abi_match) /* free the duplicated one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) kfree(_manifest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) /* validate header magic, size and type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) static int soc_valid_header(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) if (le32_to_cpu(hdr->size) != sizeof(*hdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) tplg->fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) /* big endian firmware objects not supported atm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) tplg->pass, hdr->magic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) soc_tplg_get_hdr_offset(tplg), tplg->fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) if (le32_to_cpu(hdr->magic) != SND_SOC_TPLG_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) "ASoC: pass %d does not have a valid header got %x at offset 0x%lx size 0x%zx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) tplg->pass, hdr->magic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) soc_tplg_get_hdr_offset(tplg), tplg->fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) /* Support ABI from version 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) if (le32_to_cpu(hdr->abi) > SND_SOC_TPLG_ABI_VERSION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) le32_to_cpu(hdr->abi) < SND_SOC_TPLG_ABI_VERSION_MIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) "ASoC: pass %d invalid ABI version got 0x%x need 0x%x at offset 0x%lx size 0x%zx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) tplg->pass, hdr->abi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) SND_SOC_TPLG_ABI_VERSION, soc_tplg_get_hdr_offset(tplg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) tplg->fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) if (hdr->payload_size == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) soc_tplg_get_hdr_offset(tplg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) /* check header type and call appropriate handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) static int soc_tplg_load_header(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) struct snd_soc_tplg_hdr *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) int (*elem_load)(struct soc_tplg *tplg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) struct snd_soc_tplg_hdr *hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) unsigned int hdr_pass;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) /* check for matching ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) if (le32_to_cpu(hdr->index) != tplg->req_index &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) tplg->req_index != SND_SOC_TPLG_INDEX_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) tplg->index = le32_to_cpu(hdr->index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) switch (le32_to_cpu(hdr->type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) case SND_SOC_TPLG_TYPE_MIXER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) case SND_SOC_TPLG_TYPE_ENUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) case SND_SOC_TPLG_TYPE_BYTES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) hdr_pass = SOC_TPLG_PASS_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) elem_load = soc_tplg_kcontrol_elems_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) case SND_SOC_TPLG_TYPE_DAPM_GRAPH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) hdr_pass = SOC_TPLG_PASS_GRAPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) elem_load = soc_tplg_dapm_graph_elems_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) case SND_SOC_TPLG_TYPE_DAPM_WIDGET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) hdr_pass = SOC_TPLG_PASS_WIDGET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) elem_load = soc_tplg_dapm_widget_elems_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) case SND_SOC_TPLG_TYPE_PCM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) hdr_pass = SOC_TPLG_PASS_PCM_DAI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) elem_load = soc_tplg_pcm_elems_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) case SND_SOC_TPLG_TYPE_DAI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) hdr_pass = SOC_TPLG_PASS_BE_DAI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) elem_load = soc_tplg_dai_elems_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) case SND_SOC_TPLG_TYPE_DAI_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) case SND_SOC_TPLG_TYPE_BACKEND_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) /* physical link configurations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) hdr_pass = SOC_TPLG_PASS_LINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) elem_load = soc_tplg_link_elems_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) case SND_SOC_TPLG_TYPE_MANIFEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) hdr_pass = SOC_TPLG_PASS_MANIFEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) elem_load = soc_tplg_manifest_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) /* bespoke vendor data object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) hdr_pass = SOC_TPLG_PASS_VENDOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) elem_load = soc_tplg_vendor_load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) if (tplg->pass == hdr_pass) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) dev_dbg(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) hdr->payload_size, hdr->type, hdr->version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) hdr->vendor_type, tplg->pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) return elem_load(tplg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) /* process the topology file headers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) static int soc_tplg_process_headers(struct soc_tplg *tplg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) struct snd_soc_tplg_hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) tplg->pass = SOC_TPLG_PASS_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) /* process the header types from start to end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) while (tplg->pass <= SOC_TPLG_PASS_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) tplg->hdr_pos = tplg->fw->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) while (!soc_tplg_is_eof(tplg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) /* make sure header is valid before loading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) ret = soc_valid_header(tplg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) "ASoC: topology: invalid header: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) } else if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) /* load the header object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) ret = soc_tplg_load_header(tplg, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) "ASoC: topology: could not load header: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) /* goto next header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) tplg->hdr_pos += le32_to_cpu(hdr->payload_size) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) sizeof(struct snd_soc_tplg_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) /* next data type pass */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) tplg->pass++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) /* signal DAPM we are complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) ret = soc_tplg_dapm_complete(tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) dev_err(tplg->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) "ASoC: failed to initialise DAPM from Firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) static int soc_tplg_load(struct soc_tplg *tplg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) ret = soc_tplg_process_headers(tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) soc_tplg_complete(tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) /* load audio component topology from "firmware" file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) int snd_soc_tplg_component_load(struct snd_soc_component *comp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) struct snd_soc_tplg_ops *ops, const struct firmware *fw, u32 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) struct soc_tplg tplg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) /* component needs to exist to keep and reference data while parsing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) if (!comp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) /* setup parsing context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) memset(&tplg, 0, sizeof(tplg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) tplg.fw = fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) tplg.dev = comp->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) tplg.comp = comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) tplg.ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) tplg.req_index = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) tplg.io_ops = ops->io_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) tplg.io_ops_count = ops->io_ops_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) tplg.bytes_ext_ops = ops->bytes_ext_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) ret = soc_tplg_load(&tplg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) /* free the created components if fail to load topology */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) snd_soc_tplg_component_remove(comp, SND_SOC_TPLG_INDEX_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) /* remove this dynamic widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) /* make sure we are a widget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) if (w->dobj.type != SND_SOC_DOBJ_WIDGET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) remove_widget(w->dapm->component, &w->dobj, SOC_TPLG_PASS_WIDGET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) /* remove all dynamic widgets from this DAPM context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) u32 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) struct snd_soc_dapm_widget *w, *next_w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) for_each_card_widgets_safe(dapm->card, w, next_w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) /* make sure we are a widget with correct context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) /* match ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) if (w->dobj.index != index &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) w->dobj.index != SND_SOC_TPLG_INDEX_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) /* check and free and dynamic widget kcontrols */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) snd_soc_tplg_widget_remove(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) snd_soc_dapm_free_widget(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) snd_soc_dapm_reset_cache(dapm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) /* remove dynamic controls from the component driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) struct snd_card *card = comp->card->snd_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) struct snd_soc_dobj *dobj, *next_dobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) int pass = SOC_TPLG_PASS_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) /* process the header types from end to start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) while (pass >= SOC_TPLG_PASS_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) /* remove mixer controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) down_write(&card->controls_rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) /* match index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) if (dobj->index != index &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) index != SND_SOC_TPLG_INDEX_ALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) switch (dobj->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) case SND_SOC_DOBJ_MIXER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) remove_mixer(comp, dobj, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) case SND_SOC_DOBJ_ENUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) remove_enum(comp, dobj, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) case SND_SOC_DOBJ_BYTES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) remove_bytes(comp, dobj, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) case SND_SOC_DOBJ_GRAPH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) remove_route(comp, dobj, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) case SND_SOC_DOBJ_WIDGET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) remove_widget(comp, dobj, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) case SND_SOC_DOBJ_PCM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) remove_dai(comp, dobj, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) case SND_SOC_DOBJ_DAI_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) remove_link(comp, dobj, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) case SND_SOC_DOBJ_BACKEND_LINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) * call link_unload ops if extra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) * deinitialization is needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) remove_backend_link(comp, dobj, pass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) dev_err(comp->dev, "ASoC: invalid component type %d for removal\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) dobj->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) up_write(&card->controls_rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) pass--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) /* let caller know if FW can be freed when no objects are left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) return !list_empty(&comp->dobj_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) EXPORT_SYMBOL_GPL(snd_soc_tplg_component_remove);