control.c (4f797f56c3786e2c6bc542b3f80e9a599b073976) | control.c (ee1e79b72e3cf5eac42ba9de827536f91d4c04e2) |
---|---|
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 <linux/leds.h> 15#include "sof-priv.h" | 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 <linux/leds.h> 15#include "sof-priv.h" |
16#include "sof-audio.h" |
|
16 17static void update_mute_led(struct snd_sof_control *scontrol, 18 struct snd_kcontrol *kcontrol, 19 struct snd_ctl_elem_value *ucontrol) 20{ 21 unsigned int temp = 0; 22 unsigned int mask; 23 int i; --- 59 unchanged lines hidden (view full) --- 83} 84 85int snd_sof_volume_put(struct snd_kcontrol *kcontrol, 86 struct snd_ctl_elem_value *ucontrol) 87{ 88 struct soc_mixer_control *sm = 89 (struct soc_mixer_control *)kcontrol->private_value; 90 struct snd_sof_control *scontrol = sm->dobj.private; | 17 18static void update_mute_led(struct snd_sof_control *scontrol, 19 struct snd_kcontrol *kcontrol, 20 struct snd_ctl_elem_value *ucontrol) 21{ 22 unsigned int temp = 0; 23 unsigned int mask; 24 int i; --- 59 unchanged lines hidden (view full) --- 84} 85 86int snd_sof_volume_put(struct snd_kcontrol *kcontrol, 87 struct snd_ctl_elem_value *ucontrol) 88{ 89 struct soc_mixer_control *sm = 90 (struct soc_mixer_control *)kcontrol->private_value; 91 struct snd_sof_control *scontrol = sm->dobj.private; |
91 struct snd_sof_dev *sdev = scontrol->sdev; | 92 struct snd_soc_component *scomp = scontrol->scomp; |
92 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 93 unsigned int i, channels = scontrol->num_channels; 94 bool change = false; 95 u32 value; 96 97 /* update each channel */ 98 for (i = 0; i < channels; i++) { 99 value = mixer_to_ipc(ucontrol->value.integer.value[i], 100 scontrol->volume_table, sm->max + 1); 101 change = change || (value != cdata->chanv[i].value); 102 cdata->chanv[i].channel = i; 103 cdata->chanv[i].value = value; 104 } 105 106 /* notify DSP of mixer updates */ | 93 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 94 unsigned int i, channels = scontrol->num_channels; 95 bool change = false; 96 u32 value; 97 98 /* update each channel */ 99 for (i = 0; i < channels; i++) { 100 value = mixer_to_ipc(ucontrol->value.integer.value[i], 101 scontrol->volume_table, sm->max + 1); 102 change = change || (value != cdata->chanv[i].value); 103 cdata->chanv[i].channel = i; 104 cdata->chanv[i].value = value; 105 } 106 107 /* notify DSP of mixer updates */ |
107 if (pm_runtime_active(sdev->dev)) 108 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, | 108 if (pm_runtime_active(scomp->dev)) 109 snd_sof_ipc_set_get_comp_data(scontrol, |
109 SOF_IPC_COMP_SET_VALUE, 110 SOF_CTRL_TYPE_VALUE_CHAN_GET, 111 SOF_CTRL_CMD_VOLUME, 112 true); 113 return change; 114} 115 116int snd_sof_switch_get(struct snd_kcontrol *kcontrol, --- 13 unchanged lines hidden (view full) --- 130} 131 132int snd_sof_switch_put(struct snd_kcontrol *kcontrol, 133 struct snd_ctl_elem_value *ucontrol) 134{ 135 struct soc_mixer_control *sm = 136 (struct soc_mixer_control *)kcontrol->private_value; 137 struct snd_sof_control *scontrol = sm->dobj.private; | 110 SOF_IPC_COMP_SET_VALUE, 111 SOF_CTRL_TYPE_VALUE_CHAN_GET, 112 SOF_CTRL_CMD_VOLUME, 113 true); 114 return change; 115} 116 117int snd_sof_switch_get(struct snd_kcontrol *kcontrol, --- 13 unchanged lines hidden (view full) --- 131} 132 133int snd_sof_switch_put(struct snd_kcontrol *kcontrol, 134 struct snd_ctl_elem_value *ucontrol) 135{ 136 struct soc_mixer_control *sm = 137 (struct soc_mixer_control *)kcontrol->private_value; 138 struct snd_sof_control *scontrol = sm->dobj.private; |
138 struct snd_sof_dev *sdev = scontrol->sdev; | 139 struct snd_soc_component *scomp = scontrol->scomp; |
139 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 140 unsigned int i, channels = scontrol->num_channels; 141 bool change = false; 142 u32 value; 143 144 /* update each channel */ 145 for (i = 0; i < channels; i++) { 146 value = ucontrol->value.integer.value[i]; 147 change = change || (value != cdata->chanv[i].value); 148 cdata->chanv[i].channel = i; 149 cdata->chanv[i].value = value; 150 } 151 152 if (scontrol->led_ctl.use_led) 153 update_mute_led(scontrol, kcontrol, ucontrol); 154 155 /* notify DSP of mixer updates */ | 140 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 141 unsigned int i, channels = scontrol->num_channels; 142 bool change = false; 143 u32 value; 144 145 /* update each channel */ 146 for (i = 0; i < channels; i++) { 147 value = ucontrol->value.integer.value[i]; 148 change = change || (value != cdata->chanv[i].value); 149 cdata->chanv[i].channel = i; 150 cdata->chanv[i].value = value; 151 } 152 153 if (scontrol->led_ctl.use_led) 154 update_mute_led(scontrol, kcontrol, ucontrol); 155 156 /* notify DSP of mixer updates */ |
156 if (pm_runtime_active(sdev->dev)) 157 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, | 157 if (pm_runtime_active(scomp->dev)) 158 snd_sof_ipc_set_get_comp_data(scontrol, |
158 SOF_IPC_COMP_SET_VALUE, 159 SOF_CTRL_TYPE_VALUE_CHAN_GET, 160 SOF_CTRL_CMD_SWITCH, 161 true); 162 163 return change; 164} 165 --- 14 unchanged lines hidden (view full) --- 180} 181 182int snd_sof_enum_put(struct snd_kcontrol *kcontrol, 183 struct snd_ctl_elem_value *ucontrol) 184{ 185 struct soc_enum *se = 186 (struct soc_enum *)kcontrol->private_value; 187 struct snd_sof_control *scontrol = se->dobj.private; | 159 SOF_IPC_COMP_SET_VALUE, 160 SOF_CTRL_TYPE_VALUE_CHAN_GET, 161 SOF_CTRL_CMD_SWITCH, 162 true); 163 164 return change; 165} 166 --- 14 unchanged lines hidden (view full) --- 181} 182 183int snd_sof_enum_put(struct snd_kcontrol *kcontrol, 184 struct snd_ctl_elem_value *ucontrol) 185{ 186 struct soc_enum *se = 187 (struct soc_enum *)kcontrol->private_value; 188 struct snd_sof_control *scontrol = se->dobj.private; |
188 struct snd_sof_dev *sdev = scontrol->sdev; | 189 struct snd_soc_component *scomp = scontrol->scomp; |
189 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 190 unsigned int i, channels = scontrol->num_channels; 191 bool change = false; 192 u32 value; 193 194 /* update each channel */ 195 for (i = 0; i < channels; i++) { 196 value = ucontrol->value.enumerated.item[i]; 197 change = change || (value != cdata->chanv[i].value); 198 cdata->chanv[i].channel = i; 199 cdata->chanv[i].value = value; 200 } 201 202 /* notify DSP of enum updates */ | 190 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 191 unsigned int i, channels = scontrol->num_channels; 192 bool change = false; 193 u32 value; 194 195 /* update each channel */ 196 for (i = 0; i < channels; i++) { 197 value = ucontrol->value.enumerated.item[i]; 198 change = change || (value != cdata->chanv[i].value); 199 cdata->chanv[i].channel = i; 200 cdata->chanv[i].value = value; 201 } 202 203 /* notify DSP of enum updates */ |
203 if (pm_runtime_active(sdev->dev)) 204 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, | 204 if (pm_runtime_active(scomp->dev)) 205 snd_sof_ipc_set_get_comp_data(scontrol, |
205 SOF_IPC_COMP_SET_VALUE, 206 SOF_CTRL_TYPE_VALUE_CHAN_GET, 207 SOF_CTRL_CMD_ENUM, 208 true); 209 210 return change; 211} 212 213int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, 214 struct snd_ctl_elem_value *ucontrol) 215{ 216 struct soc_bytes_ext *be = 217 (struct soc_bytes_ext *)kcontrol->private_value; 218 struct snd_sof_control *scontrol = be->dobj.private; | 206 SOF_IPC_COMP_SET_VALUE, 207 SOF_CTRL_TYPE_VALUE_CHAN_GET, 208 SOF_CTRL_CMD_ENUM, 209 true); 210 211 return change; 212} 213 214int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, 215 struct snd_ctl_elem_value *ucontrol) 216{ 217 struct soc_bytes_ext *be = 218 (struct soc_bytes_ext *)kcontrol->private_value; 219 struct snd_sof_control *scontrol = be->dobj.private; |
219 struct snd_sof_dev *sdev = scontrol->sdev; | 220 struct snd_soc_component *scomp = scontrol->scomp; |
220 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 221 struct sof_abi_hdr *data = cdata->data; 222 size_t size; 223 int ret = 0; 224 225 if (be->max > sizeof(ucontrol->value.bytes.data)) { | 221 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 222 struct sof_abi_hdr *data = cdata->data; 223 size_t size; 224 int ret = 0; 225 226 if (be->max > sizeof(ucontrol->value.bytes.data)) { |
226 dev_err_ratelimited(sdev->dev, | 227 dev_err_ratelimited(scomp->dev, |
227 "error: data max %d exceeds ucontrol data array size\n", 228 be->max); 229 return -EINVAL; 230 } 231 232 size = data->size + sizeof(*data); 233 if (size > be->max) { | 228 "error: data max %d exceeds ucontrol data array size\n", 229 be->max); 230 return -EINVAL; 231 } 232 233 size = data->size + sizeof(*data); 234 if (size > be->max) { |
234 dev_err_ratelimited(sdev->dev, | 235 dev_err_ratelimited(scomp->dev, |
235 "error: DSP sent %zu bytes max is %d\n", 236 size, be->max); 237 ret = -EINVAL; 238 goto out; 239 } 240 241 /* copy back to kcontrol */ 242 memcpy(ucontrol->value.bytes.data, data, size); 243 244out: 245 return ret; 246} 247 248int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, 249 struct snd_ctl_elem_value *ucontrol) 250{ 251 struct soc_bytes_ext *be = 252 (struct soc_bytes_ext *)kcontrol->private_value; 253 struct snd_sof_control *scontrol = be->dobj.private; | 236 "error: DSP sent %zu bytes max is %d\n", 237 size, be->max); 238 ret = -EINVAL; 239 goto out; 240 } 241 242 /* copy back to kcontrol */ 243 memcpy(ucontrol->value.bytes.data, data, size); 244 245out: 246 return ret; 247} 248 249int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, 250 struct snd_ctl_elem_value *ucontrol) 251{ 252 struct soc_bytes_ext *be = 253 (struct soc_bytes_ext *)kcontrol->private_value; 254 struct snd_sof_control *scontrol = be->dobj.private; |
254 struct snd_sof_dev *sdev = scontrol->sdev; | 255 struct snd_soc_component *scomp = scontrol->scomp; |
255 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 256 struct sof_abi_hdr *data = cdata->data; 257 size_t size = data->size + sizeof(*data); 258 259 if (be->max > sizeof(ucontrol->value.bytes.data)) { | 256 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 257 struct sof_abi_hdr *data = cdata->data; 258 size_t size = data->size + sizeof(*data); 259 260 if (be->max > sizeof(ucontrol->value.bytes.data)) { |
260 dev_err_ratelimited(sdev->dev, | 261 dev_err_ratelimited(scomp->dev, |
261 "error: data max %d exceeds ucontrol data array size\n", 262 be->max); 263 return -EINVAL; 264 } 265 266 if (size > be->max) { | 262 "error: data max %d exceeds ucontrol data array size\n", 263 be->max); 264 return -EINVAL; 265 } 266 267 if (size > be->max) { |
267 dev_err_ratelimited(sdev->dev, | 268 dev_err_ratelimited(scomp->dev, |
268 "error: size too big %zu bytes max is %d\n", 269 size, be->max); 270 return -EINVAL; 271 } 272 273 /* copy from kcontrol */ 274 memcpy(data, ucontrol->value.bytes.data, size); 275 276 /* notify DSP of byte control updates */ | 269 "error: size too big %zu bytes max is %d\n", 270 size, be->max); 271 return -EINVAL; 272 } 273 274 /* copy from kcontrol */ 275 memcpy(data, ucontrol->value.bytes.data, size); 276 277 /* notify DSP of byte control updates */ |
277 if (pm_runtime_active(sdev->dev)) 278 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, | 278 if (pm_runtime_active(scomp->dev)) 279 snd_sof_ipc_set_get_comp_data(scontrol, |
279 SOF_IPC_COMP_SET_DATA, 280 SOF_CTRL_TYPE_DATA_SET, 281 scontrol->cmd, 282 true); 283 284 return 0; 285} 286 287int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, 288 const unsigned int __user *binary_data, 289 unsigned int size) 290{ 291 struct soc_bytes_ext *be = 292 (struct soc_bytes_ext *)kcontrol->private_value; 293 struct snd_sof_control *scontrol = be->dobj.private; | 280 SOF_IPC_COMP_SET_DATA, 281 SOF_CTRL_TYPE_DATA_SET, 282 scontrol->cmd, 283 true); 284 285 return 0; 286} 287 288int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, 289 const unsigned int __user *binary_data, 290 unsigned int size) 291{ 292 struct soc_bytes_ext *be = 293 (struct soc_bytes_ext *)kcontrol->private_value; 294 struct snd_sof_control *scontrol = be->dobj.private; |
294 struct snd_sof_dev *sdev = scontrol->sdev; | 295 struct snd_soc_component *scomp = scontrol->scomp; |
295 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 296 struct snd_ctl_tlv header; 297 const struct snd_ctl_tlv __user *tlvd = 298 (const struct snd_ctl_tlv __user *)binary_data; 299 300 /* 301 * The beginning of bytes data contains a header from where 302 * the length (as bytes) is needed to know the correct copy 303 * length of data from tlvd->tlv. 304 */ 305 if (copy_from_user(&header, tlvd, sizeof(const struct snd_ctl_tlv))) 306 return -EFAULT; 307 308 /* be->max is coming from topology */ 309 if (header.length > be->max) { | 296 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 297 struct snd_ctl_tlv header; 298 const struct snd_ctl_tlv __user *tlvd = 299 (const struct snd_ctl_tlv __user *)binary_data; 300 301 /* 302 * The beginning of bytes data contains a header from where 303 * the length (as bytes) is needed to know the correct copy 304 * length of data from tlvd->tlv. 305 */ 306 if (copy_from_user(&header, tlvd, sizeof(const struct snd_ctl_tlv))) 307 return -EFAULT; 308 309 /* be->max is coming from topology */ 310 if (header.length > be->max) { |
310 dev_err_ratelimited(sdev->dev, "error: Bytes data size %d exceeds max %d.\n", | 311 dev_err_ratelimited(scomp->dev, "error: Bytes data size %d exceeds max %d.\n", |
311 header.length, be->max); 312 return -EINVAL; 313 } 314 315 /* Check that header id matches the command */ 316 if (header.numid != scontrol->cmd) { | 312 header.length, be->max); 313 return -EINVAL; 314 } 315 316 /* Check that header id matches the command */ 317 if (header.numid != scontrol->cmd) { |
317 dev_err_ratelimited(sdev->dev, | 318 dev_err_ratelimited(scomp->dev, |
318 "error: incorrect numid %d\n", 319 header.numid); 320 return -EINVAL; 321 } 322 323 if (copy_from_user(cdata->data, tlvd->tlv, header.length)) 324 return -EFAULT; 325 326 if (cdata->data->magic != SOF_ABI_MAGIC) { | 319 "error: incorrect numid %d\n", 320 header.numid); 321 return -EINVAL; 322 } 323 324 if (copy_from_user(cdata->data, tlvd->tlv, header.length)) 325 return -EFAULT; 326 327 if (cdata->data->magic != SOF_ABI_MAGIC) { |
327 dev_err_ratelimited(sdev->dev, | 328 dev_err_ratelimited(scomp->dev, |
328 "error: Wrong ABI magic 0x%08x.\n", 329 cdata->data->magic); 330 return -EINVAL; 331 } 332 333 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { | 329 "error: Wrong ABI magic 0x%08x.\n", 330 cdata->data->magic); 331 return -EINVAL; 332 } 333 334 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { |
334 dev_err_ratelimited(sdev->dev, "error: Incompatible ABI version 0x%08x.\n", | 335 dev_err_ratelimited(scomp->dev, "error: Incompatible ABI version 0x%08x.\n", |
335 cdata->data->abi); 336 return -EINVAL; 337 } 338 339 if (cdata->data->size + sizeof(const struct sof_abi_hdr) > be->max) { | 336 cdata->data->abi); 337 return -EINVAL; 338 } 339 340 if (cdata->data->size + sizeof(const struct sof_abi_hdr) > be->max) { |
340 dev_err_ratelimited(sdev->dev, "error: Mismatch in ABI data size (truncated?).\n"); | 341 dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n"); |
341 return -EINVAL; 342 } 343 344 /* notify DSP of byte control updates */ | 342 return -EINVAL; 343 } 344 345 /* notify DSP of byte control updates */ |
345 if (pm_runtime_active(sdev->dev)) 346 snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol, | 346 if (pm_runtime_active(scomp->dev)) 347 snd_sof_ipc_set_get_comp_data(scontrol, |
347 SOF_IPC_COMP_SET_DATA, 348 SOF_CTRL_TYPE_DATA_SET, 349 scontrol->cmd, 350 true); 351 352 return 0; 353} 354 355int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, 356 unsigned int __user *binary_data, 357 unsigned int size) 358{ 359 struct soc_bytes_ext *be = 360 (struct soc_bytes_ext *)kcontrol->private_value; 361 struct snd_sof_control *scontrol = be->dobj.private; | 348 SOF_IPC_COMP_SET_DATA, 349 SOF_CTRL_TYPE_DATA_SET, 350 scontrol->cmd, 351 true); 352 353 return 0; 354} 355 356int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, 357 unsigned int __user *binary_data, 358 unsigned int size) 359{ 360 struct soc_bytes_ext *be = 361 (struct soc_bytes_ext *)kcontrol->private_value; 362 struct snd_sof_control *scontrol = be->dobj.private; |
362 struct snd_sof_dev *sdev = scontrol->sdev; | 363 struct snd_soc_component *scomp = scontrol->scomp; |
363 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 364 struct snd_ctl_tlv header; 365 struct snd_ctl_tlv __user *tlvd = 366 (struct snd_ctl_tlv __user *)binary_data; 367 int data_size; 368 int ret = 0; 369 370 /* --- 6 unchanged lines hidden (view full) --- 377 cdata->data->magic = SOF_ABI_MAGIC; 378 cdata->data->abi = SOF_ABI_VERSION; 379 380 /* Prevent read of other kernel data or possibly corrupt response */ 381 data_size = cdata->data->size + sizeof(const struct sof_abi_hdr); 382 383 /* check data size doesn't exceed max coming from topology */ 384 if (data_size > be->max) { | 364 struct sof_ipc_ctrl_data *cdata = scontrol->control_data; 365 struct snd_ctl_tlv header; 366 struct snd_ctl_tlv __user *tlvd = 367 (struct snd_ctl_tlv __user *)binary_data; 368 int data_size; 369 int ret = 0; 370 371 /* --- 6 unchanged lines hidden (view full) --- 378 cdata->data->magic = SOF_ABI_MAGIC; 379 cdata->data->abi = SOF_ABI_VERSION; 380 381 /* Prevent read of other kernel data or possibly corrupt response */ 382 data_size = cdata->data->size + sizeof(const struct sof_abi_hdr); 383 384 /* check data size doesn't exceed max coming from topology */ 385 if (data_size > be->max) { |
385 dev_err_ratelimited(sdev->dev, "error: user data size %d exceeds max size %d.\n", | 386 dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %d.\n", |
386 data_size, be->max); 387 ret = -EINVAL; 388 goto out; 389 } 390 391 header.numid = scontrol->cmd; 392 header.length = data_size; 393 if (copy_to_user(tlvd, &header, sizeof(const struct snd_ctl_tlv))) { 394 ret = -EFAULT; 395 goto out; 396 } 397 398 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) 399 ret = -EFAULT; 400 401out: 402 return ret; 403} | 387 data_size, be->max); 388 ret = -EINVAL; 389 goto out; 390 } 391 392 header.numid = scontrol->cmd; 393 header.length = data_size; 394 if (copy_to_user(tlvd, &header, sizeof(const struct snd_ctl_tlv))) { 395 ret = -EFAULT; 396 goto out; 397 } 398 399 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) 400 ret = -EFAULT; 401 402out: 403 return ret; 404} |