1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2021-2022 Intel Corporation 4 // 5 // Authors: Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com> 6 // Cezary Rojewski <cezary.rojewski@intel.com> 7 // 8 9 #include <linux/cleanup.h> 10 #include <sound/soc.h> 11 #include "avs.h" 12 #include "control.h" 13 #include "messages.h" 14 #include "path.h" 15 16 static struct avs_dev *avs_get_kcontrol_adev(struct snd_kcontrol *kcontrol) 17 { 18 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); 19 struct device *dev = snd_soc_dapm_to_dev(dapm); 20 21 return to_avs_dev(dev); 22 } 23 24 static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, u32 id) 25 { 26 struct avs_path *path; 27 struct avs_path_pipeline *ppl; 28 struct avs_path_module *mod; 29 30 spin_lock(&adev->path_list_lock); 31 list_for_each_entry(path, &adev->path_list, node) { 32 list_for_each_entry(ppl, &path->ppl_list, node) { 33 list_for_each_entry(mod, &ppl->mod_list, node) { 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) { 39 spin_unlock(&adev->path_list_lock); 40 return mod; 41 } 42 } 43 } 44 } 45 spin_unlock(&adev->path_list_lock); 46 47 return NULL; 48 } 49 50 int avs_control_volume_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 51 { 52 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 53 struct avs_control_data *ctl_data = mc->dobj.private; 54 struct avs_path_module *active_module; 55 struct avs_volume_cfg *dspvols; 56 struct avs_dev *adev; 57 size_t num_dspvols; 58 int ret, i; 59 60 adev = avs_get_kcontrol_adev(kctl); 61 62 /* Prevent access to modules while path is being constructed. */ 63 guard(mutex)(&adev->path_mutex); 64 65 active_module = avs_get_volume_module(adev, ctl_data->id); 66 if (active_module) { 67 ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id, 68 active_module->instance_id, &dspvols, 69 &num_dspvols); 70 if (ret) 71 return AVS_IPC_RET(ret); 72 73 /* Do not copy more than the control can store. */ 74 num_dspvols = min_t(u32, num_dspvols, SND_SOC_TPLG_MAX_CHAN); 75 for (i = 0; i < num_dspvols; i++) 76 ctl_data->values[i] = dspvols[i].target_volume; 77 kfree(dspvols); 78 } 79 80 memcpy(uctl->value.integer.value, ctl_data->values, sizeof(ctl_data->values)); 81 return 0; 82 } 83 84 int avs_control_volume_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 85 { 86 struct avs_path_module *active_module; 87 struct avs_control_data *ctl_data; 88 struct soc_mixer_control *mc; 89 struct avs_dev *adev; 90 long *input; 91 int ret, i; 92 93 mc = (struct soc_mixer_control *)kctl->private_value; 94 ctl_data = mc->dobj.private; 95 adev = avs_get_kcontrol_adev(kctl); 96 input = uctl->value.integer.value; 97 i = 0; 98 99 /* mc->num_channels can be 0. */ 100 do { 101 if (input[i] < mc->min || input[i] > mc->max) 102 return -EINVAL; 103 } while (++i < mc->num_channels); 104 105 if (!memcmp(ctl_data->values, input, sizeof(ctl_data->values))) 106 return 0; 107 108 /* Prevent access to modules while path is being constructed. */ 109 guard(mutex)(&adev->path_mutex); 110 111 active_module = avs_get_volume_module(adev, ctl_data->id); 112 if (active_module) { 113 ret = avs_peakvol_set_volume(adev, active_module, mc, input); 114 if (ret) 115 return ret; 116 } 117 118 memcpy(ctl_data->values, input, sizeof(ctl_data->values)); 119 return 1; 120 } 121 122 int avs_control_volume_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) 123 { 124 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 125 126 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 127 uinfo->count = max_t(u32, 1, mc->num_channels); 128 uinfo->value.integer.min = 0; 129 uinfo->value.integer.max = mc->max; 130 return 0; 131 } 132 133 int avs_control_mute_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 134 { 135 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 136 struct avs_control_data *ctl_data = mc->dobj.private; 137 struct avs_path_module *active_module; 138 struct avs_mute_cfg *dspmutes; 139 struct avs_dev *adev; 140 size_t num_dspmutes; 141 int ret, i; 142 143 adev = avs_get_kcontrol_adev(kctl); 144 145 /* Prevent access to modules while path is being constructed. */ 146 guard(mutex)(&adev->path_mutex); 147 148 active_module = avs_get_volume_module(adev, ctl_data->id); 149 if (active_module) { 150 ret = avs_ipc_peakvol_get_mute(adev, active_module->module_id, 151 active_module->instance_id, &dspmutes, 152 &num_dspmutes); 153 if (ret) 154 return AVS_IPC_RET(ret); 155 156 /* Do not copy more than the control can store. */ 157 num_dspmutes = min_t(u32, num_dspmutes, SND_SOC_TPLG_MAX_CHAN); 158 for (i = 0; i < num_dspmutes; i++) 159 ctl_data->values[i] = !dspmutes[i].mute; 160 kfree(dspmutes); 161 } 162 163 memcpy(uctl->value.integer.value, ctl_data->values, sizeof(ctl_data->values)); 164 return 0; 165 } 166 167 int avs_control_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) 168 { 169 struct avs_path_module *active_module; 170 struct avs_control_data *ctl_data; 171 struct soc_mixer_control *mc; 172 struct avs_dev *adev; 173 long *input; 174 int ret, i; 175 176 mc = (struct soc_mixer_control *)kctl->private_value; 177 ctl_data = mc->dobj.private; 178 adev = avs_get_kcontrol_adev(kctl); 179 input = uctl->value.integer.value; 180 i = 0; 181 182 /* mc->num_channels can be 0. */ 183 do { 184 if (input[i] < mc->min || input[i] > mc->max) 185 return -EINVAL; 186 } while (++i < mc->num_channels); 187 188 if (!memcmp(ctl_data->values, input, sizeof(ctl_data->values))) 189 return 0; 190 191 /* Prevent access to modules while path is being constructed. */ 192 guard(mutex)(&adev->path_mutex); 193 194 active_module = avs_get_volume_module(adev, ctl_data->id); 195 if (active_module) { 196 ret = avs_peakvol_set_mute(adev, active_module, mc, input); 197 if (ret) 198 return ret; 199 } 200 201 memcpy(ctl_data->values, input, sizeof(ctl_data->values)); 202 return 1; 203 } 204 205 int avs_control_mute_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) 206 { 207 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 208 209 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 210 uinfo->count = max_t(u32, 1, mc->num_channels); 211 uinfo->value.integer.min = 0; 212 uinfo->value.integer.max = mc->max; 213 return 0; 214 } 215