diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-25 16:55:16 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-25 16:55:16 -0700 |
commit | d7227785e384d4422b3ca189aa5bf19f462337cc (patch) | |
tree | fbd117e5e3f31a8561f6b6d159413bc744f460e5 /sound/soc/sof/topology.c | |
parent | 2518f226c60d8e04d18ba4295500a5b0b8ac7659 (diff) | |
parent | 60571929d06b028800f27b51a7c81de1144944cf (diff) |
Merge tag 'sound-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"Not much dramatic changes at this time, but we've received quite a lot
of changes for ASoC, while there are still a few fixes and quirks for
usual HD- and USB-auido. Here are some highlights.
ASoC:
- Overhaul of endianness specification for data formats, avoiding
needless restrictions due to CODECs
- Initial stages of Intel AVS driver merge
- Introduction of v4 IPC mechanism for SOF
- TDM mode support for AK4613
- Support for Analog Devices ADAU1361, Cirrus Logic CS35L45, Maxim
MAX98396, MediaTek MT8186, NXP i.MX8 micfil and SAI interfaces,
nVidia Tegra186 ASRC, and Texas Instruments TAS2764 and TAS2780
Others:
- A few regression fixes after the USB-audio endpoint management
refactoring
- More enhancements for Cirrus HD-audio codec support (still ongoing)
- Addition of generic serial MIDI driver"
* tag 'sound-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (504 commits)
ALSA: hda/realtek - Add new type for ALC245
ALSA: usb-audio: Configure sync endpoints before data
ALSA: ctxfi: fix typo in comment
ALSA: cs5535audio: fix typo in comment
ALSA: ctxfi: Add SB046x PCI ID
ALSA: usb-audio: Add missing ep_idx in fixed EP quirks
ALSA: usb-audio: Workaround for clock setup on TEAC devices
ALSA: lola: Bounds check loop iterator against streams array size
ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv()
ASoC: rt1308-sdw: add the default value of register 0xc320
ASoC: rt9120: Use pm_runtime and regcache to optimize 'pwdnn' logic
ASoC: rt9120: Fix 3byte read, valule offset typo
ASoC: amd: acp: Set Speaker enable/disable pin through rt1019 codec driver.
ASoC: amd: acp: Set Speaker enable/disable pin through rt1019 codec driver
ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition()
ASoC: codecs: lpass: Fix passing zero to 'PTR_ERR'
ASoC: SOF: sof-client-ipc-flood-test: use pm_runtime_resume_and_get()
ASoC: SOF: mediatek: remove duplicate include in mt8195.c
ASoC: SOF: mediatek: Add mt8195 debug dump
ASoC: SOF: mediatek: Add mediatek common debug dump
...
Diffstat (limited to 'sound/soc/sof/topology.c')
-rw-r--r-- | sound/soc/sof/topology.c | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 3e5b319b44c7..b1fcab7ce48e 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -32,7 +32,6 @@ #define VOL_HALF_DB_STEP 50 /* TLV data items */ -#define TLV_ITEMS 3 #define TLV_MIN 0 #define TLV_STEP 1 #define TLV_MUTE 2 @@ -134,7 +133,7 @@ int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum so return 0; } -static inline int get_tlv_data(const int *p, int tlv[TLV_ITEMS]) +static inline int get_tlv_data(const int *p, int tlv[SOF_TLV_ITEMS]) { /* we only support dB scale TLV type at the moment */ if ((int)p[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE) @@ -224,7 +223,7 @@ static u32 vol_pow32(u32 a, int exp, u32 fwl) * Function to calculate volume gain from TLV data. * This function can only handle gain steps that are multiples of 0.5 dB */ -static u32 vol_compute_gain(u32 value, int *tlv) +u32 vol_compute_gain(u32 value, int *tlv) { int dB_gain; u32 linear_gain; @@ -263,20 +262,17 @@ static u32 vol_compute_gain(u32 value, int *tlv) * "size" specifies the number of entries in the table */ static int set_up_volume_table(struct snd_sof_control *scontrol, - int tlv[TLV_ITEMS], int size) + int tlv[SOF_TLV_ITEMS], int size) { - int j; - - /* init the volume table */ - scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL); - if (!scontrol->volume_table) - return -ENOMEM; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - /* populate the volume table */ - for (j = 0; j < size ; j++) - scontrol->volume_table[j] = vol_compute_gain(j, tlv); + if (tplg_ops->control->set_up_volume_table) + return tplg_ops->control->set_up_volume_table(scontrol, tlv, size); - return 0; + dev_err(scomp->dev, "Mandatory op %s not set\n", __func__); + return -EINVAL; } struct sof_dai_types { @@ -772,7 +768,8 @@ static int sof_control_load_volume(struct snd_soc_component *scomp, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_mixer_control *mc = container_of(hdr, struct snd_soc_tplg_mixer_control, hdr); - int tlv[TLV_ITEMS]; + int tlv[SOF_TLV_ITEMS]; + unsigned int mask; int ret; /* validate topology data */ @@ -821,6 +818,16 @@ skip: goto err; } + if (scontrol->led_ctl.use_led) { + mask = scontrol->led_ctl.direction ? SNDRV_CTL_ELEM_ACCESS_MIC_LED : + SNDRV_CTL_ELEM_ACCESS_SPK_LED; + scontrol->access &= ~SNDRV_CTL_ELEM_ACCESS_LED_MASK; + scontrol->access |= mask; + kc->access &= ~SNDRV_CTL_ELEM_ACCESS_LED_MASK; + kc->access |= mask; + sdev->led_present = true; + } + dev_dbg(scomp->dev, "tplg: load kcontrol index %d chans %d\n", scontrol->comp_id, scontrol->num_channels); @@ -1001,15 +1008,18 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp, struct snd_soc_dai *cpu_dai; int i; + if (!w->sname) { + dev_err(scomp->dev, "Widget %s does not have stream\n", w->name); + return -EINVAL; + } + list_for_each_entry(rtd, &card->rtd_list, list) { dev_vdbg(scomp->dev, "tplg: check widget: %s stream: %s dai stream: %s\n", w->name, w->sname, rtd->dai_link->stream_name); - if (!w->sname || !rtd->dai_link->stream_name) - continue; - /* does stream match DAI link ? */ - if (strcmp(w->sname, rtd->dai_link->stream_name)) + if (!rtd->dai_link->stream_name || + strcmp(w->sname, rtd->dai_link->stream_name)) continue; switch (w->id) { @@ -1140,7 +1150,6 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s const struct sof_token_info *token_list = ipc_tplg_ops->token_list; struct snd_soc_tplg_private *private = &tw->priv; int num_tuples = 0; - size_t size; int ret, i; if (count > 0 && !object_token_list) { @@ -1153,8 +1162,7 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s num_tuples += token_list[object_token_list[i]].count; /* allocate memory for tuples array */ - size = sizeof(struct snd_sof_tuple) * num_tuples; - swidget->tuples = kzalloc(size, GFP_KERNEL); + swidget->tuples = kcalloc(num_tuples, sizeof(*swidget->tuples), GFP_KERNEL); if (!swidget->tuples) return -ENOMEM; @@ -1595,7 +1603,6 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_ const struct sof_token_info *token_list = ipc_tplg_ops->token_list; struct snd_soc_tplg_private *private = &cfg->priv; struct snd_sof_dai_link *slink; - size_t size; u32 token_id = 0; int num_tuples = 0; int ret, num_sets; @@ -1707,22 +1714,23 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_ } /* allocate memory for tuples array */ - size = sizeof(struct snd_sof_tuple) * num_tuples; - slink->tuples = kzalloc(size, GFP_KERNEL); + slink->tuples = kcalloc(num_tuples, sizeof(*slink->tuples), GFP_KERNEL); if (!slink->tuples) { kfree(slink->hw_configs); kfree(slink); return -ENOMEM; } - /* parse one set of DAI link tokens */ - ret = sof_copy_tuples(sdev, private->array, le32_to_cpu(private->size), - SOF_DAI_LINK_TOKENS, 1, slink->tuples, - num_tuples, &slink->num_tuples); - if (ret < 0) { - dev_err(scomp->dev, "failed to parse %s for dai link %s\n", - token_list[SOF_DAI_LINK_TOKENS].name, link->name); - goto err; + if (token_list[SOF_DAI_LINK_TOKENS].tokens) { + /* parse one set of DAI link tokens */ + ret = sof_copy_tuples(sdev, private->array, le32_to_cpu(private->size), + SOF_DAI_LINK_TOKENS, 1, slink->tuples, + num_tuples, &slink->num_tuples); + if (ret < 0) { + dev_err(scomp->dev, "failed to parse %s for dai link %s\n", + token_list[SOF_DAI_LINK_TOKENS].name, link->name); + goto err; + } } /* nothing more to do if there are no DAI type-specific tokens defined */ @@ -2075,6 +2083,7 @@ static struct snd_soc_tplg_ops sof_tplg_ops = { int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) { + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); const struct firmware *fw; int ret; @@ -2097,6 +2106,10 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) } release_firmware(fw); + + if (ret >= 0 && sdev->led_present) + ret = snd_ctl_led_request(); + return ret; } EXPORT_SYMBOL(snd_sof_load_topology); |