Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: Intel: avs: Mute and multi-channel controls

Merge series from Cezary Rojewski <cezary.rojewski@intel.com>:

Note: the patchset DOES provide functional changes to the ASoC
framework.

Current kcontrols loaded with ASoC topology allow for mono or stereo
configuration only. To expand this and provide support to up to 8
channels, first address the limitations found within the ASoC core and
then update the user (avs-driver) so that it can utilize these new
functionality. The 8 channels max stems from SND_SOC_TPLG_MAX_CHAN
constant which is part of UAPI - asoc.h.

For the ASoC side, two changes are made:

- drop the ambiguous usage of ops.info when determining the kcontrol
type
- save the num_channels value which is already part of the ALSA-topology
but is currently skipped by ASoC core when loading mixer controls

For the avs-driver side, merge PEAKVOL IPCs as there is basically no
difference between the handles and then do the same with the control
operations. The merge for the latter is done is two steps: first provide
new implementation which honors the multi-channel controls and then move
to it while dropping the now-duplicated code.

Amadeusz Sławiński (2):
ASoC: Intel: avs: Add volume control for GAIN module
ASoC: Intel: avs: Add support for mute for PEAKVOL and GAIN

Cezary Rojewski (8):
ASoC: topology: Create kcontrols based on their type
ASoC: topology: Save num_channels value for mixer controls
ASoC: Intel: avs: Make PEAKVOL configurable from topology
ASoC: Intel: avs: Update VOLUME and add MUTE IPCs
ASoC: Intel: avs: New volume control operations
ASoC: Intel: avs: Move to the new control operations
ASoC: Intel: avs: Honor the invert flag for mixer controls
ASoC: Intel: avs: Support multi-channel PEAKVOL instantiation

include/sound/soc.h | 1 +
include/uapi/sound/intel/avs/tokens.h | 4 +
sound/soc/intel/avs/control.c | 180 ++++++++++++++++++++------
sound/soc/intel/avs/control.h | 12 +-
sound/soc/intel/avs/messages.c | 111 +++++++++++++++-
sound/soc/intel/avs/messages.h | 24 +++-
sound/soc/intel/avs/path.c | 108 ++++++++++++++--
sound/soc/intel/avs/path.h | 5 +
sound/soc/intel/avs/topology.c | 47 ++++++-
sound/soc/intel/avs/topology.h | 5 +
sound/soc/soc-topology.c | 55 +++-----
11 files changed, 440 insertions(+), 112 deletions(-)

--
2.25.1

+444 -116
+1
include/sound/soc.h
··· 1254 1254 int min, max, platform_max; 1255 1255 int reg, rreg; 1256 1256 unsigned int shift, rshift; 1257 + u32 num_channels; 1257 1258 unsigned int sign_bit; 1258 1259 unsigned int invert:1; 1259 1260 unsigned int autodisable:1;
+4
include/uapi/sound/intel/avs/tokens.h
··· 84 84 AVS_TKN_MODCFG_WHM_DMA_TYPE_U32 = 437, 85 85 AVS_TKN_MODCFG_WHM_DMABUFF_SIZE_U32 = 438, 86 86 AVS_TKN_MODCFG_WHM_BLOB_AFMT_ID_U32 = 439, 87 + AVS_TKN_MODCFG_PEAKVOL_VOLUME_U32 = 440, 88 + AVS_TKN_MODCFG_PEAKVOL_CHANNEL_ID_U32 = 441, /* reserved */ 89 + AVS_TKN_MODCFG_PEAKVOL_CURVE_TYPE_U32 = 442, 90 + AVS_TKN_MODCFG_PEAKVOL_CURVE_DURATION_U32 = 443, 87 91 88 92 /* struct avs_tplg_pplcfg */ 89 93 AVS_TKN_PPLCFG_ID_U32 = 1401,
+143 -41
sound/soc/intel/avs/control.c
··· 6 6 // Cezary Rojewski <cezary.rojewski@intel.com> 7 7 // 8 8 9 + #include <linux/cleanup.h> 9 10 #include <sound/soc.h> 10 11 #include "avs.h" 11 12 #include "control.h" ··· 32 31 list_for_each_entry(path, &adev->path_list, node) { 33 32 list_for_each_entry(ppl, &path->ppl_list, node) { 34 33 list_for_each_entry(mod, &ppl->mod_list, node) { 35 - if (guid_equal(&mod->template->cfg_ext->type, &AVS_PEAKVOL_MOD_UUID) 36 - && mod->template->ctl_id == id) { 34 + guid_t *type = &mod->template->cfg_ext->type; 35 + 36 + if ((guid_equal(type, &AVS_PEAKVOL_MOD_UUID) || 37 + guid_equal(type, &AVS_GAIN_MOD_UUID)) && 38 + mod->template->ctl_id == id) { 37 39 spin_unlock(&adev->path_list_lock); 38 40 return mod; 39 41 } ··· 48 44 return NULL; 49 45 } 50 46 51 - int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 47 + int avs_control_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 52 48 { 53 - struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 54 - struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private; 55 - struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol); 56 - struct avs_volume_cfg *dspvols = NULL; 49 + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 50 + struct avs_control_data *ctl_data = mc->dobj.private; 57 51 struct avs_path_module *active_module; 52 + struct avs_volume_cfg *dspvols; 53 + struct avs_dev *adev; 58 54 size_t num_dspvols; 59 - int ret = 0; 55 + int ret, i; 60 56 61 - /* prevent access to modules while path is being constructed */ 62 - mutex_lock(&adev->path_mutex); 57 + adev = avs_get_kcontrol_adev(kctl); 58 + 59 + /* Prevent access to modules while path is being constructed. */ 60 + guard(mutex)(&adev->path_mutex); 63 61 64 62 active_module = avs_get_volume_module(adev, ctl_data->id); 65 63 if (active_module) { 66 64 ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id, 67 65 active_module->instance_id, &dspvols, 68 66 &num_dspvols); 69 - if (!ret) 70 - ucontrol->value.integer.value[0] = dspvols[0].target_volume; 67 + if (ret) 68 + return AVS_IPC_RET(ret); 71 69 72 - ret = AVS_IPC_RET(ret); 70 + /* Do not copy more than the control can store. */ 71 + num_dspvols = min_t(u32, num_dspvols, SND_SOC_TPLG_MAX_CHAN); 72 + for (i = 0; i < num_dspvols; i++) 73 + ctl_data->values[i] = dspvols[i].target_volume; 73 74 kfree(dspvols); 74 - } else { 75 - ucontrol->value.integer.value[0] = ctl_data->volume; 76 75 } 77 76 78 - mutex_unlock(&adev->path_mutex); 79 - return ret; 77 + memcpy(uctl->value.integer.value, ctl_data->values, sizeof(ctl_data->values)); 78 + return 0; 80 79 } 81 80 82 - int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 81 + int avs_control_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 83 82 { 84 - struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; 85 - struct avs_control_data *ctl_data = (struct avs_control_data *)mc->dobj.private; 86 - struct avs_dev *adev = avs_get_kcontrol_adev(kcontrol); 87 - long *volume = &ctl_data->volume; 88 83 struct avs_path_module *active_module; 89 - struct avs_volume_cfg dspvol = {0}; 90 - long ctlvol = ucontrol->value.integer.value[0]; 91 - int ret = 0, changed = 0; 84 + struct avs_control_data *ctl_data; 85 + struct soc_mixer_control *mc; 86 + struct avs_dev *adev; 87 + long *input; 88 + int ret, i; 92 89 93 - if (ctlvol < 0 || ctlvol > mc->max) 94 - return -EINVAL; 90 + mc = (struct soc_mixer_control *)kctl->private_value; 91 + ctl_data = mc->dobj.private; 92 + adev = avs_get_kcontrol_adev(kctl); 93 + input = uctl->value.integer.value; 94 + i = 0; 95 95 96 - /* prevent access to modules while path is being constructed */ 97 - mutex_lock(&adev->path_mutex); 96 + /* mc->num_channels can be 0. */ 97 + do { 98 + if (input[i] < mc->min || input[i] > mc->max) 99 + return -EINVAL; 100 + } while (++i < mc->num_channels); 98 101 99 - if (*volume != ctlvol) { 100 - *volume = ctlvol; 101 - changed = 1; 102 - } 102 + if (!memcmp(ctl_data->values, input, sizeof(ctl_data->values))) 103 + return 0; 104 + 105 + /* Prevent access to modules while path is being constructed. */ 106 + guard(mutex)(&adev->path_mutex); 103 107 104 108 active_module = avs_get_volume_module(adev, ctl_data->id); 105 109 if (active_module) { 106 - dspvol.channel_id = AVS_ALL_CHANNELS_MASK; 107 - dspvol.target_volume = *volume; 108 - 109 - ret = avs_ipc_peakvol_set_volume(adev, active_module->module_id, 110 - active_module->instance_id, &dspvol); 111 - ret = AVS_IPC_RET(ret); 110 + ret = avs_peakvol_set_volume(adev, active_module, mc, input); 111 + if (ret) 112 + return ret; 112 113 } 113 114 114 - mutex_unlock(&adev->path_mutex); 115 + memcpy(ctl_data->values, input, sizeof(ctl_data->values)); 116 + return 1; 117 + } 115 118 116 - return ret ? ret : changed; 119 + int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) 120 + { 121 + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 122 + 123 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 124 + uinfo->count = max_t(u32, 1, mc->num_channels); 125 + uinfo->value.integer.min = 0; 126 + uinfo->value.integer.max = mc->max; 127 + return 0; 128 + } 129 + 130 + int avs_control_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 131 + { 132 + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 133 + struct avs_control_data *ctl_data = mc->dobj.private; 134 + struct avs_path_module *active_module; 135 + struct avs_mute_cfg *dspmutes; 136 + struct avs_dev *adev; 137 + size_t num_dspmutes; 138 + int ret, i; 139 + 140 + adev = avs_get_kcontrol_adev(kctl); 141 + 142 + /* Prevent access to modules while path is being constructed. */ 143 + guard(mutex)(&adev->path_mutex); 144 + 145 + active_module = avs_get_volume_module(adev, ctl_data->id); 146 + if (active_module) { 147 + ret = avs_ipc_peakvol_get_mute(adev, active_module->module_id, 148 + active_module->instance_id, &dspmutes, 149 + &num_dspmutes); 150 + if (ret) 151 + return AVS_IPC_RET(ret); 152 + 153 + /* Do not copy more than the control can store. */ 154 + num_dspmutes = min_t(u32, num_dspmutes, SND_SOC_TPLG_MAX_CHAN); 155 + for (i = 0; i < num_dspmutes; i++) 156 + ctl_data->values[i] = !dspmutes[i].mute; 157 + kfree(dspmutes); 158 + } 159 + 160 + memcpy(uctl->value.integer.value, ctl_data->values, sizeof(ctl_data->values)); 161 + return 0; 162 + } 163 + 164 + int avs_control_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 165 + { 166 + struct avs_path_module *active_module; 167 + struct avs_control_data *ctl_data; 168 + struct soc_mixer_control *mc; 169 + struct avs_dev *adev; 170 + long *input; 171 + int ret, i; 172 + 173 + mc = (struct soc_mixer_control *)kctl->private_value; 174 + ctl_data = mc->dobj.private; 175 + adev = avs_get_kcontrol_adev(kctl); 176 + input = uctl->value.integer.value; 177 + i = 0; 178 + 179 + /* mc->num_channels can be 0. */ 180 + do { 181 + if (input[i] < mc->min || input[i] > mc->max) 182 + return -EINVAL; 183 + } while (++i < mc->num_channels); 184 + 185 + if (!memcmp(ctl_data->values, input, sizeof(ctl_data->values))) 186 + return 0; 187 + 188 + /* Prevent access to modules while path is being constructed. */ 189 + guard(mutex)(&adev->path_mutex); 190 + 191 + active_module = avs_get_volume_module(adev, ctl_data->id); 192 + if (active_module) { 193 + ret = avs_peakvol_set_mute(adev, active_module, mc, input); 194 + if (ret) 195 + return ret; 196 + } 197 + 198 + memcpy(ctl_data->values, input, sizeof(ctl_data->values)); 199 + return 1; 200 + } 201 + 202 + int avs_control_mute_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) 203 + { 204 + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 205 + 206 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 207 + uinfo->count = max_t(u32, 1, mc->num_channels); 208 + uinfo->value.integer.min = 0; 209 + uinfo->value.integer.max = mc->max; 210 + return 0; 117 211 }
+8 -4
sound/soc/intel/avs/control.h
··· 10 10 #define __SOUND_SOC_INTEL_AVS_CTRL_H 11 11 12 12 #include <sound/control.h> 13 + #include <uapi/sound/asoc.h> 13 14 14 15 struct avs_control_data { 15 16 u32 id; 16 - 17 - long volume; 17 + long values[SND_SOC_TPLG_MAX_CHAN]; 18 18 }; 19 19 20 - int avs_control_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); 21 - int avs_control_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); 20 + int avs_control_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); 21 + int avs_control_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); 22 + int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo); 23 + int avs_control_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); 24 + int avs_control_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl); 25 + int avs_control_mute_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo); 22 26 23 27 #endif
+104 -7
sound/soc/intel/avs/messages.c
··· 677 677 (u8 *)&cpr_fmt, sizeof(cpr_fmt)); 678 678 } 679 679 680 - int avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, 681 - struct avs_volume_cfg *vol) 682 - { 683 - return avs_ipc_set_large_config(adev, module_id, instance_id, AVS_PEAKVOL_VOLUME, (u8 *)vol, 684 - sizeof(*vol)); 685 - } 686 - 687 680 int avs_ipc_peakvol_get_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, 688 681 struct avs_volume_cfg **vols, size_t *num_vols) 689 682 { ··· 697 704 *num_vols = payload_size / sizeof(**vols); 698 705 699 706 return 0; 707 + } 708 + 709 + int avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, 710 + struct avs_volume_cfg *vol) 711 + { 712 + return avs_ipc_set_large_config(adev, module_id, instance_id, AVS_PEAKVOL_VOLUME, 713 + (u8 *)vol, sizeof(*vol)); 714 + } 715 + 716 + int avs_ipc_peakvol_set_volumes(struct avs_dev *adev, u16 module_id, u8 instance_id, 717 + struct avs_volume_cfg *vols, size_t num_vols) 718 + { 719 + struct avs_tlv *tlv; 720 + size_t offset; 721 + size_t size; 722 + u8 *payload; 723 + int ret, i; 724 + 725 + size = num_vols * sizeof(*vols); 726 + size += num_vols * sizeof(*tlv); 727 + if (size > AVS_MAILBOX_SIZE) 728 + return -EINVAL; 729 + 730 + payload = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL); 731 + if (!payload) 732 + return -ENOMEM; 733 + 734 + for (offset = i = 0; i < num_vols; i++) { 735 + tlv = (struct avs_tlv *)(payload + offset); 736 + 737 + tlv->type = AVS_PEAKVOL_VOLUME; 738 + tlv->length = sizeof(*vols); 739 + memcpy(tlv->value, &vols[i], tlv->length); 740 + 741 + offset += sizeof(*tlv) + tlv->length; 742 + } 743 + 744 + ret = avs_ipc_set_large_config(adev, module_id, instance_id, AVS_VENDOR_CONFIG, payload, 745 + size); 746 + kfree(payload); 747 + return ret; 748 + } 749 + 750 + int avs_ipc_peakvol_get_mute(struct avs_dev *adev, u16 module_id, u8 instance_id, 751 + struct avs_mute_cfg **mutes, size_t *num_mutes) 752 + { 753 + size_t payload_size; 754 + u8 *payload; 755 + int ret; 756 + 757 + ret = avs_ipc_get_large_config(adev, module_id, instance_id, AVS_PEAKVOL_MUTE, NULL, 0, 758 + &payload, &payload_size); 759 + if (ret) 760 + return ret; 761 + 762 + /* Non-zero payload expected for PEAKVOL_MUTE. */ 763 + if (!payload_size) 764 + return -EREMOTEIO; 765 + 766 + *mutes = (struct avs_mute_cfg *)payload; 767 + *num_mutes = payload_size / sizeof(**mutes); 768 + 769 + return 0; 770 + } 771 + 772 + int avs_ipc_peakvol_set_mute(struct avs_dev *adev, u16 module_id, u8 instance_id, 773 + struct avs_mute_cfg *mute) 774 + { 775 + return avs_ipc_set_large_config(adev, module_id, instance_id, AVS_PEAKVOL_MUTE, 776 + (u8 *)mute, sizeof(*mute)); 777 + } 778 + 779 + int avs_ipc_peakvol_set_mutes(struct avs_dev *adev, u16 module_id, u8 instance_id, 780 + struct avs_mute_cfg *mutes, size_t num_mutes) 781 + { 782 + struct avs_tlv *tlv; 783 + size_t offset; 784 + size_t size; 785 + u8 *payload; 786 + int ret, i; 787 + 788 + size = num_mutes * sizeof(*mutes); 789 + size += num_mutes * sizeof(*tlv); 790 + if (size > AVS_MAILBOX_SIZE) 791 + return -EINVAL; 792 + 793 + payload = kzalloc(AVS_MAILBOX_SIZE, GFP_KERNEL); 794 + if (!payload) 795 + return -ENOMEM; 796 + 797 + for (offset = i = 0; i < num_mutes; i++) { 798 + tlv = (struct avs_tlv *)(payload + offset); 799 + 800 + tlv->type = AVS_PEAKVOL_MUTE; 801 + tlv->length = sizeof(*mutes); 802 + memcpy(tlv->value, &mutes[i], tlv->length); 803 + 804 + offset += sizeof(*tlv) + tlv->length; 805 + } 806 + 807 + ret = avs_ipc_set_large_config(adev, module_id, instance_id, AVS_VENDOR_CONFIG, payload, 808 + size); 809 + kfree(payload); 810 + return ret; 700 811 } 701 812 702 813 #ifdef CONFIG_DEBUG_FS
+22 -2
sound/soc/intel/avs/messages.h
··· 814 814 } __packed; 815 815 static_assert(sizeof(struct avs_volume_cfg) == 24); 816 816 817 + struct avs_mute_cfg { 818 + u32 channel_id; 819 + u32 mute; 820 + u32 curve_type; 821 + u32 reserved; /* alignment */ 822 + u64 curve_duration; 823 + } __packed; 824 + static_assert(sizeof(struct avs_mute_cfg) == 24); 825 + 817 826 struct avs_peakvol_cfg { 818 827 struct avs_modcfg_base base; 819 828 struct avs_volume_cfg vols[]; ··· 905 896 906 897 /* Module runtime parameters */ 907 898 899 + #define AVS_VENDOR_CONFIG 0xFF 900 + 908 901 enum avs_copier_runtime_param { 909 902 AVS_COPIER_SET_SINK_FORMAT = 2, 910 903 }; ··· 925 914 926 915 enum avs_peakvol_runtime_param { 927 916 AVS_PEAKVOL_VOLUME = 0, 917 + AVS_PEAKVOL_MUTE = 3, 928 918 }; 929 919 930 920 enum avs_audio_curve_type { ··· 933 921 AVS_AUDIO_CURVE_WINDOWS_FADE = 1, 934 922 }; 935 923 936 - int avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, 937 - struct avs_volume_cfg *vol); 938 924 int avs_ipc_peakvol_get_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, 939 925 struct avs_volume_cfg **vols, size_t *num_vols); 926 + int avs_ipc_peakvol_set_volume(struct avs_dev *adev, u16 module_id, u8 instance_id, 927 + struct avs_volume_cfg *vol); 928 + int avs_ipc_peakvol_set_volumes(struct avs_dev *adev, u16 module_id, u8 instance_id, 929 + struct avs_volume_cfg *vols, size_t num_vols); 930 + int avs_ipc_peakvol_get_mute(struct avs_dev *adev, u16 module_id, u8 instance_id, 931 + struct avs_mute_cfg **mutes, size_t *num_mutes); 932 + int avs_ipc_peakvol_set_mute(struct avs_dev *adev, u16 module_id, u8 instance_id, 933 + struct avs_mute_cfg *mute); 934 + int avs_ipc_peakvol_set_mutes(struct avs_dev *adev, u16 module_id, u8 instance_id, 935 + struct avs_mute_cfg *mutes, size_t num_mutes); 940 936 941 937 #define AVS_PROBE_INST_ID 0 942 938
+94 -14
sound/soc/intel/avs/path.c
··· 300 300 return ret; 301 301 } 302 302 303 - static struct avs_control_data *avs_get_module_control(struct avs_path_module *mod) 303 + static struct soc_mixer_control *avs_get_module_control(struct avs_path_module *mod, 304 + const char *name) 304 305 { 305 306 struct avs_tplg_module *t = mod->template; 306 307 struct avs_tplg_path_template *path_tmpl; ··· 317 316 318 317 mc = (struct soc_mixer_control *)w->kcontrols[i]->private_value; 319 318 ctl_data = (struct avs_control_data *)mc->dobj.private; 320 - if (ctl_data->id == t->ctl_id) 321 - return ctl_data; 319 + if (ctl_data->id == t->ctl_id && strstr(w->kcontrols[i]->id.name, name)) 320 + return mc; 322 321 } 323 322 324 323 return NULL; 325 324 } 326 325 326 + int avs_peakvol_set_volume(struct avs_dev *adev, struct avs_path_module *mod, 327 + struct soc_mixer_control *mc, long *input) 328 + { 329 + struct avs_volume_cfg vols[SND_SOC_TPLG_MAX_CHAN] = {{0}}; 330 + struct avs_control_data *ctl_data; 331 + struct avs_tplg_module *t; 332 + int ret, i; 333 + 334 + ctl_data = mc->dobj.private; 335 + t = mod->template; 336 + if (!input) 337 + input = ctl_data->values; 338 + 339 + if (mc->num_channels) { 340 + for (i = 0; i < mc->num_channels; i++) { 341 + vols[i].channel_id = i; 342 + vols[i].target_volume = input[i]; 343 + vols[i].curve_type = t->cfg_ext->peakvol.curve_type; 344 + vols[i].curve_duration = t->cfg_ext->peakvol.curve_duration; 345 + } 346 + 347 + ret = avs_ipc_peakvol_set_volumes(adev, mod->module_id, mod->instance_id, vols, 348 + mc->num_channels); 349 + return AVS_IPC_RET(ret); 350 + } 351 + 352 + /* Target all channels if no individual selected. */ 353 + vols[0].channel_id = AVS_ALL_CHANNELS_MASK; 354 + vols[0].target_volume = input[0]; 355 + vols[0].curve_type = t->cfg_ext->peakvol.curve_type; 356 + vols[0].curve_duration = t->cfg_ext->peakvol.curve_duration; 357 + 358 + ret = avs_ipc_peakvol_set_volume(adev, mod->module_id, mod->instance_id, &vols[0]); 359 + return AVS_IPC_RET(ret); 360 + } 361 + 362 + int avs_peakvol_set_mute(struct avs_dev *adev, struct avs_path_module *mod, 363 + struct soc_mixer_control *mc, long *input) 364 + { 365 + struct avs_mute_cfg mutes[SND_SOC_TPLG_MAX_CHAN] = {{0}}; 366 + struct avs_control_data *ctl_data; 367 + struct avs_tplg_module *t; 368 + int ret, i; 369 + 370 + ctl_data = mc->dobj.private; 371 + t = mod->template; 372 + if (!input) 373 + input = ctl_data->values; 374 + 375 + if (mc->num_channels) { 376 + for (i = 0; i < mc->num_channels; i++) { 377 + mutes[i].channel_id = i; 378 + mutes[i].mute = !input[i]; 379 + mutes[i].curve_type = t->cfg_ext->peakvol.curve_type; 380 + mutes[i].curve_duration = t->cfg_ext->peakvol.curve_duration; 381 + } 382 + 383 + ret = avs_ipc_peakvol_set_mutes(adev, mod->module_id, mod->instance_id, mutes, 384 + mc->num_channels); 385 + return AVS_IPC_RET(ret); 386 + } 387 + 388 + /* Target all channels if no individual selected. */ 389 + mutes[0].channel_id = AVS_ALL_CHANNELS_MASK; 390 + mutes[0].mute = !input[0]; 391 + mutes[0].curve_type = t->cfg_ext->peakvol.curve_type; 392 + mutes[0].curve_duration = t->cfg_ext->peakvol.curve_duration; 393 + 394 + ret = avs_ipc_peakvol_set_mute(adev, mod->module_id, mod->instance_id, &mutes[0]); 395 + return AVS_IPC_RET(ret); 396 + } 397 + 327 398 static int avs_peakvol_create(struct avs_dev *adev, struct avs_path_module *mod) 328 399 { 329 400 struct avs_tplg_module *t = mod->template; 330 - struct avs_control_data *ctl_data; 401 + struct soc_mixer_control *mc; 331 402 struct avs_peakvol_cfg *cfg; 332 - int volume = S32_MAX; 333 403 size_t cfg_size; 334 404 int ret; 335 405 336 - ctl_data = avs_get_module_control(mod); 337 - if (ctl_data) 338 - volume = ctl_data->volume; 339 - 340 - /* As 2+ channels controls are unsupported, have a single block for all channels. */ 341 406 cfg_size = struct_size(cfg, vols, 1); 342 407 if (cfg_size > AVS_MAILBOX_SIZE) 343 408 return -EINVAL; ··· 415 348 cfg->base.obs = t->cfg_base->obs; 416 349 cfg->base.is_pages = t->cfg_base->is_pages; 417 350 cfg->base.audio_fmt = *t->in_fmt; 418 - cfg->vols[0].target_volume = volume; 419 351 cfg->vols[0].channel_id = AVS_ALL_CHANNELS_MASK; 420 - cfg->vols[0].curve_type = AVS_AUDIO_CURVE_NONE; 421 - cfg->vols[0].curve_duration = 0; 352 + cfg->vols[0].target_volume = S32_MAX; 353 + cfg->vols[0].curve_type = t->cfg_ext->peakvol.curve_type; 354 + cfg->vols[0].curve_duration = t->cfg_ext->peakvol.curve_duration; 422 355 423 356 ret = avs_dsp_init_module(adev, mod->module_id, mod->owner->instance_id, t->core_id, 424 357 t->domain, cfg, cfg_size, &mod->instance_id); 358 + if (ret) 359 + return ret; 425 360 426 - return ret; 361 + /* Now configure both VOLUME and MUTE parameters. */ 362 + mc = avs_get_module_control(mod, "Volume"); 363 + if (mc) { 364 + ret = avs_peakvol_set_volume(adev, mod, mc, NULL); 365 + if (ret) 366 + return ret; 367 + } 368 + 369 + mc = avs_get_module_control(mod, "Switch"); 370 + if (mc) 371 + return avs_peakvol_set_mute(adev, mod, mc, NULL); 372 + return 0; 427 373 } 428 374 429 375 static int avs_updown_mix_create(struct avs_dev *adev, struct avs_path_module *mod)
+5
sound/soc/intel/avs/path.h
··· 69 69 int avs_path_pause(struct avs_path *path); 70 70 int avs_path_run(struct avs_path *path, int trigger); 71 71 72 + int avs_peakvol_set_volume(struct avs_dev *adev, struct avs_path_module *mod, 73 + struct soc_mixer_control *mc, long *input); 74 + int avs_peakvol_set_mute(struct avs_dev *adev, struct avs_path_module *mod, 75 + struct soc_mixer_control *mc, long *input); 76 + 72 77 #endif
+41 -6
sound/soc/intel/avs/topology.c
··· 857 857 .offset = offsetof(struct avs_tplg_modcfg_ext, whm.blob_fmt), 858 858 .parse = avs_parse_audio_format_ptr, 859 859 }, 860 + { 861 + .token = AVS_TKN_MODCFG_PEAKVOL_VOLUME_U32, 862 + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 863 + .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.target_volume), 864 + .parse = avs_parse_word_token, 865 + }, 866 + { 867 + .token = AVS_TKN_MODCFG_PEAKVOL_CURVE_TYPE_U32, 868 + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 869 + .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.curve_type), 870 + .parse = avs_parse_word_token, 871 + }, 872 + { 873 + .token = AVS_TKN_MODCFG_PEAKVOL_CURVE_DURATION_U32, 874 + .type = SND_SOC_TPLG_TUPLE_TYPE_WORD, 875 + .offset = offsetof(struct avs_tplg_modcfg_ext, peakvol.curve_duration), 876 + .parse = avs_parse_word_token, 877 + }, 860 878 }; 861 879 862 880 static const struct avs_tplg_token_parser pin_format_parsers[] = { ··· 1905 1887 return 0; 1906 1888 } 1907 1889 1908 - #define AVS_CONTROL_OPS_VOLUME 257 1890 + enum { 1891 + AVS_CONTROL_OPS_VOLUME = 257, 1892 + AVS_CONTROL_OPS_MUTE, 1893 + }; 1909 1894 1910 1895 static const struct snd_soc_tplg_kcontrol_ops avs_control_ops[] = { 1911 1896 { 1912 1897 .id = AVS_CONTROL_OPS_VOLUME, 1913 1898 .get = avs_control_volume_get, 1914 1899 .put = avs_control_volume_put, 1900 + .info = avs_control_volume_info, 1901 + }, 1902 + { 1903 + .id = AVS_CONTROL_OPS_MUTE, 1904 + .get = avs_control_mute_get, 1905 + .put = avs_control_mute_put, 1906 + .info = avs_control_mute_info, 1915 1907 }, 1916 1908 }; 1917 1909 ··· 1943 1915 struct avs_control_data *ctl_data; 1944 1916 struct soc_mixer_control *mc; 1945 1917 size_t block_size; 1946 - int ret; 1918 + int ret, i; 1947 1919 1948 1920 switch (le32_to_cpu(hdr->type)) { 1949 1921 case SND_SOC_TPLG_TYPE_MIXER: 1950 - tmc = container_of(hdr, typeof(*tmc), hdr); 1951 - tuples = tmc->priv.array; 1952 - block_size = le32_to_cpu(tmc->priv.size); 1953 1922 break; 1954 1923 default: 1955 1924 return -EINVAL; 1956 1925 } 1926 + 1927 + mc = (struct soc_mixer_control *)ctmpl->private_value; 1928 + tmc = container_of(hdr, typeof(*tmc), hdr); 1929 + tuples = tmc->priv.array; 1930 + block_size = le32_to_cpu(tmc->priv.size); 1957 1931 1958 1932 ctl_data = devm_kzalloc(comp->card->dev, sizeof(*ctl_data), GFP_KERNEL); 1959 1933 if (!ctl_data) ··· 1967 1937 if (ret) 1968 1938 return ret; 1969 1939 1970 - mc = (struct soc_mixer_control *)ctmpl->private_value; 1971 1940 mc->dobj.private = ctl_data; 1941 + if (tmc->invert) { 1942 + ctl_data->values[0] = mc->max; 1943 + for (i = 1; i < mc->num_channels; i++) 1944 + ctl_data->values[i] = mc->max; 1945 + } 1946 + 1972 1947 return 0; 1973 1948 } 1974 1949
+5
sound/soc/intel/avs/topology.h
··· 113 113 struct { 114 114 struct avs_audio_format *out_fmt; 115 115 } micsel; 116 + struct { 117 + u32 target_volume; 118 + u32 curve_type; 119 + u32 curve_duration; 120 + } peakvol; 116 121 }; 117 122 }; 118 123
+17 -42
sound/soc/soc-topology.c
··· 220 220 return -EINVAL; 221 221 } 222 222 223 - static inline void soc_bind_err(struct soc_tplg *tplg, 224 - struct snd_soc_tplg_ctl_hdr *hdr, int index) 225 - { 226 - dev_err(tplg->dev, 227 - "ASoC: invalid control type (g,p,i) %d:%d:%d index %d at 0x%lx\n", 228 - hdr->ops.get, hdr->ops.put, hdr->ops.info, index, 229 - soc_tplg_get_offset(tplg)); 230 - } 231 - 232 223 static inline void soc_control_err(struct soc_tplg *tplg, 233 224 struct snd_soc_tplg_ctl_hdr *hdr, const char *name) 234 225 { ··· 669 678 sm->min = le32_to_cpu(mc->min); 670 679 sm->invert = le32_to_cpu(mc->invert); 671 680 sm->platform_max = le32_to_cpu(mc->platform_max); 681 + sm->num_channels = le32_to_cpu(mc->num_channels); 672 682 673 683 /* map io handlers */ 674 684 err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); ··· 984 992 return -EINVAL; 985 993 } 986 994 987 - switch (le32_to_cpu(control_hdr->ops.info)) { 988 - case SND_SOC_TPLG_CTL_VOLSW: 989 - case SND_SOC_TPLG_CTL_STROBE: 990 - case SND_SOC_TPLG_CTL_VOLSW_SX: 991 - case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 992 - case SND_SOC_TPLG_CTL_RANGE: 993 - case SND_SOC_TPLG_DAPM_CTL_VOLSW: 994 - case SND_SOC_TPLG_DAPM_CTL_PIN: 995 + switch (le32_to_cpu(control_hdr->type)) { 996 + case SND_SOC_TPLG_TYPE_MIXER: 995 997 ret = soc_tplg_dmixer_create(tplg, le32_to_cpu(hdr->payload_size)); 996 998 break; 997 - case SND_SOC_TPLG_CTL_ENUM: 998 - case SND_SOC_TPLG_CTL_ENUM_VALUE: 999 - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 1000 - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 1001 - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 999 + case SND_SOC_TPLG_TYPE_ENUM: 1002 1000 ret = soc_tplg_denum_create(tplg, le32_to_cpu(hdr->payload_size)); 1003 1001 break; 1004 - case SND_SOC_TPLG_CTL_BYTES: 1002 + case SND_SOC_TPLG_TYPE_BYTES: 1005 1003 ret = soc_tplg_dbytes_create(tplg, le32_to_cpu(hdr->payload_size)); 1006 1004 break; 1007 1005 default: 1008 - soc_bind_err(tplg, control_hdr, i); 1009 - return -EINVAL; 1010 - } 1011 - if (ret < 0) { 1012 - dev_err(tplg->dev, "ASoC: invalid control\n"); 1013 - return ret; 1006 + ret = -EINVAL; 1007 + break; 1014 1008 } 1015 1009 1010 + if (ret < 0) { 1011 + dev_err(tplg->dev, "ASoC: invalid control type: %d, index: %d at 0x%lx\n", 1012 + control_hdr->type, i, soc_tplg_get_offset(tplg)); 1013 + return ret; 1014 + } 1016 1015 } 1017 1016 1018 1017 return 0; ··· 1167 1184 1168 1185 for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) { 1169 1186 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; 1170 - switch (le32_to_cpu(control_hdr->ops.info)) { 1171 - case SND_SOC_TPLG_CTL_VOLSW: 1172 - case SND_SOC_TPLG_CTL_STROBE: 1173 - case SND_SOC_TPLG_CTL_VOLSW_SX: 1174 - case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 1175 - case SND_SOC_TPLG_CTL_RANGE: 1176 - case SND_SOC_TPLG_DAPM_CTL_VOLSW: 1187 + 1188 + switch (le32_to_cpu(control_hdr->type)) { 1189 + case SND_SOC_TPLG_TYPE_MIXER: 1177 1190 /* volume mixer */ 1178 1191 kc[i].index = mixer_count; 1179 1192 kcontrol_type[i] = SND_SOC_TPLG_TYPE_MIXER; ··· 1178 1199 if (ret < 0) 1179 1200 goto hdr_err; 1180 1201 break; 1181 - case SND_SOC_TPLG_CTL_ENUM: 1182 - case SND_SOC_TPLG_CTL_ENUM_VALUE: 1183 - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: 1184 - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: 1185 - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: 1202 + case SND_SOC_TPLG_TYPE_ENUM: 1186 1203 /* enumerated mixer */ 1187 1204 kc[i].index = enum_count; 1188 1205 kcontrol_type[i] = SND_SOC_TPLG_TYPE_ENUM; ··· 1187 1212 if (ret < 0) 1188 1213 goto hdr_err; 1189 1214 break; 1190 - case SND_SOC_TPLG_CTL_BYTES: 1215 + case SND_SOC_TPLG_TYPE_BYTES: 1191 1216 /* bytes control */ 1192 1217 kc[i].index = bytes_count; 1193 1218 kcontrol_type[i] = SND_SOC_TPLG_TYPE_BYTES;