1 // SPDX-License-Identifier: (GPL-2.0 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 "sof-priv.h" 15 16 static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size) 17 { 18 if (value >= size) 19 return volume_map[size - 1]; 20 21 return volume_map[value]; 22 } 23 24 static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size) 25 { 26 int i; 27 28 for (i = 0; i < size; i++) { 29 if (volume_map[i] >= value) 30 return i; 31 } 32 33 return i - 1; 34 } 35 36 int snd_sof_volume_get(struct snd_kcontrol *kcontrol, 37 struct snd_ctl_elem_value *ucontrol) 38 { 39 struct soc_mixer_control *sm = 40 (struct soc_mixer_control *)kcontrol->private_value; 41 struct snd_sof_control *scontrol = sm->dobj.private; 42 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 43 unsigned int i, channels = scontrol->num_channels; 44 45 /* read back each channel */ 46 for (i = 0; i < channels; i++) 47 ucontrol->value.integer.value[i] = 48 ipc_to_mixer(cdata->chanv[i].value, 49 scontrol->volume_table, sm->max + 1); 50 51 return 0; 52 } 53 54 int snd_sof_volume_put(struct snd_kcontrol *kcontrol, 55 struct snd_ctl_elem_value *ucontrol) 56 { 57 struct soc_mixer_control *sm = 58 (struct soc_mixer_control *)kcontrol->private_value; 59 struct snd_sof_control *scontrol = sm->dobj.private; 60 struct snd_sof_dev *sdev = scontrol->sdev; 61 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 62 unsigned int i, channels = scontrol->num_channels; 63 64 /* update each channel */ 65 for (i = 0; i < channels; i++) { 66 cdata->chanv[i].value = 67 mixer_to_ipc(ucontrol->value.integer.value[i], 68 scontrol->volume_table, sm->max + 1); 69 cdata->chanv[i].channel = i; 70 } 71 72 /* notify DSP of mixer updates */ 73 if (pm_runtime_active(sdev->dev)) 74 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, 75 SOF_IPC_COMP_SET_VALUE, 76 SOF_CTRL_TYPE_VALUE_CHAN_GET, 77 SOF_CTRL_CMD_VOLUME, 78 true); 79 80 return 0; 81 } 82 83 int snd_sof_switch_get(struct snd_kcontrol *kcontrol, 84 struct snd_ctl_elem_value *ucontrol) 85 { 86 struct soc_mixer_control *sm = 87 (struct soc_mixer_control *)kcontrol->private_value; 88 struct snd_sof_control *scontrol = sm->dobj.private; 89 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 90 unsigned int i, channels = scontrol->num_channels; 91 92 /* read back each channel */ 93 for (i = 0; i < channels; i++) 94 ucontrol->value.integer.value[i] = cdata->chanv[i].value; 95 96 return 0; 97 } 98 99 int snd_sof_switch_put(struct snd_kcontrol *kcontrol, 100 struct snd_ctl_elem_value *ucontrol) 101 { 102 struct soc_mixer_control *sm = 103 (struct soc_mixer_control *)kcontrol->private_value; 104 struct snd_sof_control *scontrol = sm->dobj.private; 105 struct snd_sof_dev *sdev = scontrol->sdev; 106 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 107 unsigned int i, channels = scontrol->num_channels; 108 109 /* update each channel */ 110 for (i = 0; i < channels; i++) { 111 cdata->chanv[i].value = ucontrol->value.integer.value[i]; 112 cdata->chanv[i].channel = i; 113 } 114 115 /* notify DSP of mixer updates */ 116 if (pm_runtime_active(sdev->dev)) 117 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, 118 SOF_IPC_COMP_SET_VALUE, 119 SOF_CTRL_TYPE_VALUE_CHAN_GET, 120 SOF_CTRL_CMD_SWITCH, 121 true); 122 123 return 0; 124 } 125 126 int snd_sof_enum_get(struct snd_kcontrol *kcontrol, 127 struct snd_ctl_elem_value *ucontrol) 128 { 129 struct soc_enum *se = 130 (struct soc_enum *)kcontrol->private_value; 131 struct snd_sof_control *scontrol = se->dobj.private; 132 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 133 unsigned int i, channels = scontrol->num_channels; 134 135 /* read back each channel */ 136 for (i = 0; i < channels; i++) 137 ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; 138 139 return 0; 140 } 141 142 int snd_sof_enum_put(struct snd_kcontrol *kcontrol, 143 struct snd_ctl_elem_value *ucontrol) 144 { 145 struct soc_enum *se = 146 (struct soc_enum *)kcontrol->private_value; 147 struct snd_sof_control *scontrol = se->dobj.private; 148 struct snd_sof_dev *sdev = scontrol->sdev; 149 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 150 unsigned int i, channels = scontrol->num_channels; 151 152 /* update each channel */ 153 for (i = 0; i < channels; i++) { 154 cdata->chanv[i].value = ucontrol->value.enumerated.item[i]; 155 cdata->chanv[i].channel = i; 156 } 157 158 /* notify DSP of enum updates */ 159 if (pm_runtime_active(sdev->dev)) 160 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, 161 SOF_IPC_COMP_SET_VALUE, 162 SOF_CTRL_TYPE_VALUE_CHAN_GET, 163 SOF_CTRL_CMD_ENUM, 164 true); 165 166 return 0; 167 } 168 169 int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, 170 struct snd_ctl_elem_value *ucontrol) 171 { 172 struct soc_bytes_ext *be = 173 (struct soc_bytes_ext *)kcontrol->private_value; 174 struct snd_sof_control *scontrol = be->dobj.private; 175 struct snd_sof_dev *sdev = scontrol->sdev; 176 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 177 struct sof_abi_hdr *data = cdata->data; 178 size_t size; 179 int ret = 0; 180 181 if (be->max > sizeof(ucontrol->value.bytes.data)) { 182 dev_err_ratelimited(sdev->dev, 183 "error: data max %d exceeds ucontrol data array size\n", 184 be->max); 185 return -EINVAL; 186 } 187 188 size = data->size + sizeof(*data); 189 if (size > be->max) { 190 dev_err_ratelimited(sdev->dev, 191 "error: DSP sent %zu bytes max is %d\n", 192 size, be->max); 193 ret = -EINVAL; 194 goto out; 195 } 196 197 /* copy back to kcontrol */ 198 memcpy(ucontrol->value.bytes.data, data, size); 199 200 out: 201 return ret; 202 } 203 204 int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, 205 struct snd_ctl_elem_value *ucontrol) 206 { 207 struct soc_bytes_ext *be = 208 (struct soc_bytes_ext *)kcontrol->private_value; 209 struct snd_sof_control *scontrol = be->dobj.private; 210 struct snd_sof_dev *sdev = scontrol->sdev; 211 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 212 struct sof_abi_hdr *data = cdata->data; 213 size_t size = data->size + sizeof(*data); 214 215 if (be->max > sizeof(ucontrol->value.bytes.data)) { 216 dev_err_ratelimited(sdev->dev, 217 "error: data max %d exceeds ucontrol data array size\n", 218 be->max); 219 return -EINVAL; 220 } 221 222 if (size > be->max) { 223 dev_err_ratelimited(sdev->dev, 224 "error: size too big %zu bytes max is %d\n", 225 size, be->max); 226 return -EINVAL; 227 } 228 229 /* copy from kcontrol */ 230 memcpy(data, ucontrol->value.bytes.data, size); 231 232 /* notify DSP of byte control updates */ 233 if (pm_runtime_active(sdev->dev)) 234 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, 235 SOF_IPC_COMP_SET_DATA, 236 SOF_CTRL_TYPE_DATA_SET, 237 scontrol->cmd, 238 true); 239 240 return 0; 241 } 242 243 int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, 244 const unsigned int __user *binary_data, 245 unsigned int size) 246 { 247 struct soc_bytes_ext *be = 248 (struct soc_bytes_ext *)kcontrol->private_value; 249 struct snd_sof_control *scontrol = be->dobj.private; 250 struct snd_sof_dev *sdev = scontrol->sdev; 251 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 252 struct snd_ctl_tlv header; 253 const struct snd_ctl_tlv __user *tlvd = 254 (const struct snd_ctl_tlv __user *)binary_data; 255 256 /* 257 * The beginning of bytes data contains a header from where 258 * the length (as bytes) is needed to know the correct copy 259 * length of data from tlvd->tlv. 260 */ 261 if (copy_from_user(&header, tlvd, sizeof(const struct snd_ctl_tlv))) 262 return -EFAULT; 263 264 /* be->max is coming from topology */ 265 if (header.length > be->max) { 266 dev_err_ratelimited(sdev->dev, "error: Bytes data size %d exceeds max %d.\n", 267 header.length, be->max); 268 return -EINVAL; 269 } 270 271 /* Check that header id matches the command */ 272 if (header.numid != scontrol->cmd) { 273 dev_err_ratelimited(sdev->dev, 274 "error: incorrect numid %d\n", 275 header.numid); 276 return -EINVAL; 277 } 278 279 if (copy_from_user(cdata->data, tlvd->tlv, header.length)) 280 return -EFAULT; 281 282 if (cdata->data->magic != SOF_ABI_MAGIC) { 283 dev_err_ratelimited(sdev->dev, 284 "error: Wrong ABI magic 0x%08x.\n", 285 cdata->data->magic); 286 return -EINVAL; 287 } 288 289 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { 290 dev_err_ratelimited(sdev->dev, "error: Incompatible ABI version 0x%08x.\n", 291 cdata->data->abi); 292 return -EINVAL; 293 } 294 295 if (cdata->data->size + sizeof(const struct sof_abi_hdr) > be->max) { 296 dev_err_ratelimited(sdev->dev, "error: Mismatch in ABI data size (truncated?).\n"); 297 return -EINVAL; 298 } 299 300 /* notify DSP of byte control updates */ 301 if (pm_runtime_active(sdev->dev)) 302 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, 303 SOF_IPC_COMP_SET_DATA, 304 SOF_CTRL_TYPE_DATA_SET, 305 scontrol->cmd, 306 true); 307 308 return 0; 309 } 310 311 int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, 312 unsigned int __user *binary_data, 313 unsigned int size) 314 { 315 struct soc_bytes_ext *be = 316 (struct soc_bytes_ext *)kcontrol->private_value; 317 struct snd_sof_control *scontrol = be->dobj.private; 318 struct snd_sof_dev *sdev = scontrol->sdev; 319 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 320 struct snd_ctl_tlv header; 321 struct snd_ctl_tlv __user *tlvd = 322 (struct snd_ctl_tlv __user *)binary_data; 323 int data_size; 324 int ret = 0; 325 326 /* 327 * Decrement the limit by ext bytes header size to 328 * ensure the user space buffer is not exceeded. 329 */ 330 size -= sizeof(const struct snd_ctl_tlv); 331 332 /* set the ABI header values */ 333 cdata->data->magic = SOF_ABI_MAGIC; 334 cdata->data->abi = SOF_ABI_VERSION; 335 336 /* Prevent read of other kernel data or possibly corrupt response */ 337 data_size = cdata->data->size + sizeof(const struct sof_abi_hdr); 338 339 /* check data size doesn't exceed max coming from topology */ 340 if (data_size > be->max) { 341 dev_err_ratelimited(sdev->dev, "error: user data size %d exceeds max size %d.\n", 342 data_size, be->max); 343 ret = -EINVAL; 344 goto out; 345 } 346 347 header.numid = scontrol->cmd; 348 header.length = data_size; 349 if (copy_to_user(tlvd, &header, sizeof(const struct snd_ctl_tlv))) { 350 ret = -EFAULT; 351 goto out; 352 } 353 354 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) 355 ret = -EFAULT; 356 357 out: 358 return ret; 359 } 360