1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // 3 // This file is provided under a dual BSD/GPLv2 license. When using or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2018 Intel Corporation. All rights reserved. 7 // 8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> 9 // 10 11 /* Mixer Controls */ 12 13 #include <linux/pm_runtime.h> 14 #include <linux/leds.h> 15 #include "sof-priv.h" 16 #include "sof-audio.h" 17 18 static void update_mute_led(struct snd_sof_control *scontrol, 19 struct snd_kcontrol *kcontrol, 20 struct snd_ctl_elem_value *ucontrol) 21 { 22 int temp = 0; 23 int mask; 24 int i; 25 26 mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 27 28 for (i = 0; i < scontrol->num_channels; i++) { 29 if (ucontrol->value.integer.value[i]) { 30 temp |= mask; 31 break; 32 } 33 } 34 35 if (temp == scontrol->led_ctl.led_value) 36 return; 37 38 scontrol->led_ctl.led_value = temp; 39 40 #if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) 41 if (!scontrol->led_ctl.direction) 42 ledtrig_audio_set(LED_AUDIO_MUTE, temp ? LED_OFF : LED_ON); 43 else 44 ledtrig_audio_set(LED_AUDIO_MICMUTE, temp ? LED_OFF : LED_ON); 45 #endif 46 } 47 48 int snd_sof_volume_get(struct snd_kcontrol *kcontrol, 49 struct snd_ctl_elem_value *ucontrol) 50 { 51 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; 52 struct snd_sof_control *scontrol = sm->dobj.private; 53 struct snd_soc_component *scomp = scontrol->scomp; 54 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 55 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 56 57 if (tplg_ops->control->volume_get) 58 return tplg_ops->control->volume_get(scontrol, ucontrol); 59 60 return 0; 61 } 62 63 int snd_sof_volume_put(struct snd_kcontrol *kcontrol, 64 struct snd_ctl_elem_value *ucontrol) 65 { 66 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; 67 struct snd_sof_control *scontrol = sm->dobj.private; 68 struct snd_soc_component *scomp = scontrol->scomp; 69 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 70 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 71 72 if (tplg_ops->control->volume_put) 73 return tplg_ops->control->volume_put(scontrol, ucontrol); 74 75 return false; 76 } 77 78 int snd_sof_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 79 { 80 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; 81 struct snd_sof_control *scontrol = sm->dobj.private; 82 unsigned int channels = scontrol->num_channels; 83 int platform_max; 84 85 if (!sm->platform_max) 86 sm->platform_max = sm->max; 87 platform_max = sm->platform_max; 88 89 if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) 90 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 91 else 92 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 93 94 uinfo->count = channels; 95 uinfo->value.integer.min = 0; 96 uinfo->value.integer.max = platform_max - sm->min; 97 return 0; 98 } 99 100 int snd_sof_switch_get(struct snd_kcontrol *kcontrol, 101 struct snd_ctl_elem_value *ucontrol) 102 { 103 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; 104 struct snd_sof_control *scontrol = sm->dobj.private; 105 struct snd_soc_component *scomp = scontrol->scomp; 106 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 107 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 108 109 if (tplg_ops->control->switch_get) 110 return tplg_ops->control->switch_get(scontrol, ucontrol); 111 112 return 0; 113 } 114 115 int snd_sof_switch_put(struct snd_kcontrol *kcontrol, 116 struct snd_ctl_elem_value *ucontrol) 117 { 118 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; 119 struct snd_sof_control *scontrol = sm->dobj.private; 120 struct snd_soc_component *scomp = scontrol->scomp; 121 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 122 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 123 124 if (scontrol->led_ctl.use_led) 125 update_mute_led(scontrol, kcontrol, ucontrol); 126 127 if (tplg_ops->control->switch_put) 128 return tplg_ops->control->switch_put(scontrol, ucontrol); 129 130 return false; 131 } 132 133 int snd_sof_enum_get(struct snd_kcontrol *kcontrol, 134 struct snd_ctl_elem_value *ucontrol) 135 { 136 struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; 137 struct snd_sof_control *scontrol = se->dobj.private; 138 struct snd_soc_component *scomp = scontrol->scomp; 139 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 140 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 141 142 if (tplg_ops->control->enum_get) 143 return tplg_ops->control->enum_get(scontrol, ucontrol); 144 145 return 0; 146 } 147 148 int snd_sof_enum_put(struct snd_kcontrol *kcontrol, 149 struct snd_ctl_elem_value *ucontrol) 150 { 151 struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; 152 struct snd_sof_control *scontrol = se->dobj.private; 153 struct snd_soc_component *scomp = scontrol->scomp; 154 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 155 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 156 157 if (tplg_ops->control->enum_put) 158 return tplg_ops->control->enum_put(scontrol, ucontrol); 159 160 return false; 161 } 162 163 int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, 164 struct snd_ctl_elem_value *ucontrol) 165 { 166 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; 167 struct snd_sof_control *scontrol = be->dobj.private; 168 struct snd_soc_component *scomp = scontrol->scomp; 169 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 170 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 171 172 if (tplg_ops->control->bytes_get) 173 return tplg_ops->control->bytes_get(scontrol, ucontrol); 174 175 return 0; 176 } 177 178 int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, 179 struct snd_ctl_elem_value *ucontrol) 180 { 181 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; 182 struct snd_sof_control *scontrol = be->dobj.private; 183 struct snd_soc_component *scomp = scontrol->scomp; 184 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 185 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 186 187 if (tplg_ops->control->bytes_put) 188 return tplg_ops->control->bytes_put(scontrol, ucontrol); 189 190 return 0; 191 } 192 193 int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, 194 const unsigned int __user *binary_data, 195 unsigned int size) 196 { 197 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; 198 struct snd_sof_control *scontrol = be->dobj.private; 199 struct snd_soc_component *scomp = scontrol->scomp; 200 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 201 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 202 203 /* make sure we have at least a header */ 204 if (size < sizeof(struct snd_ctl_tlv)) 205 return -EINVAL; 206 207 if (tplg_ops->control->bytes_ext_put) 208 return tplg_ops->control->bytes_ext_put(scontrol, binary_data, size); 209 210 return 0; 211 } 212 213 int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data, 214 unsigned int size) 215 { 216 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; 217 struct snd_sof_control *scontrol = be->dobj.private; 218 struct snd_soc_component *scomp = scontrol->scomp; 219 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 220 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 221 int ret, err; 222 223 ret = pm_runtime_get_sync(scomp->dev); 224 if (ret < 0 && ret != -EACCES) { 225 dev_err_ratelimited(scomp->dev, "%s: failed to resume %d\n", __func__, ret); 226 pm_runtime_put_noidle(scomp->dev); 227 return ret; 228 } 229 230 if (tplg_ops->control->bytes_ext_volatile_get) 231 ret = tplg_ops->control->bytes_ext_volatile_get(scontrol, binary_data, size); 232 233 pm_runtime_mark_last_busy(scomp->dev); 234 err = pm_runtime_put_autosuspend(scomp->dev); 235 if (err < 0) 236 dev_err_ratelimited(scomp->dev, "%s: failed to idle %d\n", __func__, err); 237 238 return ret; 239 } 240 241 int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, 242 unsigned int __user *binary_data, 243 unsigned int size) 244 { 245 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; 246 struct snd_sof_control *scontrol = be->dobj.private; 247 struct snd_soc_component *scomp = scontrol->scomp; 248 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 249 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 250 251 if (tplg_ops->control->bytes_ext_get) 252 return tplg_ops->control->bytes_ext_get(scontrol, binary_data, size); 253 254 return 0; 255 } 256