root/sound/soc/sof/control.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mixer_to_ipc
  2. ipc_to_mixer
  3. snd_sof_volume_get
  4. snd_sof_volume_put
  5. snd_sof_switch_get
  6. snd_sof_switch_put
  7. snd_sof_enum_get
  8. snd_sof_enum_put
  9. snd_sof_bytes_get
  10. snd_sof_bytes_put
  11. snd_sof_bytes_ext_put
  12. snd_sof_bytes_ext_get

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

/* [<][>][^][v][top][bottom][index][help] */