linux/sound/soc/sof/control.c
<<
>>
Prefs
   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
  18static 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
  48static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
  49{
  50        if (value >= size)
  51                return volume_map[size - 1];
  52
  53        return volume_map[value];
  54}
  55
  56static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size)
  57{
  58        int i;
  59
  60        for (i = 0; i < size; i++) {
  61                if (volume_map[i] >= value)
  62                        return i;
  63        }
  64
  65        return i - 1;
  66}
  67
  68int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
  69                       struct snd_ctl_elem_value *ucontrol)
  70{
  71        struct soc_mixer_control *sm =
  72                (struct soc_mixer_control *)kcontrol->private_value;
  73        struct snd_sof_control *scontrol = sm->dobj.private;
  74        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
  75        unsigned int i, channels = scontrol->num_channels;
  76
  77        /* read back each channel */
  78        for (i = 0; i < channels; i++)
  79                ucontrol->value.integer.value[i] =
  80                        ipc_to_mixer(cdata->chanv[i].value,
  81                                     scontrol->volume_table, sm->max + 1);
  82
  83        return 0;
  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;
  92        struct snd_soc_component *scomp = scontrol->scomp;
  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 */
 108        if (pm_runtime_active(scomp->dev))
 109                snd_sof_ipc_set_get_comp_data(scontrol,
 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_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 118{
 119        struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
 120        struct snd_sof_control *scontrol = sm->dobj.private;
 121        unsigned int channels = scontrol->num_channels;
 122        int platform_max;
 123
 124        if (!sm->platform_max)
 125                sm->platform_max = sm->max;
 126        platform_max = sm->platform_max;
 127
 128        if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
 129                uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 130        else
 131                uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 132
 133        uinfo->count = channels;
 134        uinfo->value.integer.min = 0;
 135        uinfo->value.integer.max = platform_max - sm->min;
 136        return 0;
 137}
 138
 139int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
 140                       struct snd_ctl_elem_value *ucontrol)
 141{
 142        struct soc_mixer_control *sm =
 143                (struct soc_mixer_control *)kcontrol->private_value;
 144        struct snd_sof_control *scontrol = sm->dobj.private;
 145        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 146        unsigned int i, channels = scontrol->num_channels;
 147
 148        /* read back each channel */
 149        for (i = 0; i < channels; i++)
 150                ucontrol->value.integer.value[i] = cdata->chanv[i].value;
 151
 152        return 0;
 153}
 154
 155int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
 156                       struct snd_ctl_elem_value *ucontrol)
 157{
 158        struct soc_mixer_control *sm =
 159                (struct soc_mixer_control *)kcontrol->private_value;
 160        struct snd_sof_control *scontrol = sm->dobj.private;
 161        struct snd_soc_component *scomp = scontrol->scomp;
 162        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 163        unsigned int i, channels = scontrol->num_channels;
 164        bool change = false;
 165        u32 value;
 166
 167        /* update each channel */
 168        for (i = 0; i < channels; i++) {
 169                value = ucontrol->value.integer.value[i];
 170                change = change || (value != cdata->chanv[i].value);
 171                cdata->chanv[i].channel = i;
 172                cdata->chanv[i].value = value;
 173        }
 174
 175        if (scontrol->led_ctl.use_led)
 176                update_mute_led(scontrol, kcontrol, ucontrol);
 177
 178        /* notify DSP of mixer updates */
 179        if (pm_runtime_active(scomp->dev))
 180                snd_sof_ipc_set_get_comp_data(scontrol,
 181                                              SOF_IPC_COMP_SET_VALUE,
 182                                              SOF_CTRL_TYPE_VALUE_CHAN_GET,
 183                                              SOF_CTRL_CMD_SWITCH,
 184                                              true);
 185
 186        return change;
 187}
 188
 189int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
 190                     struct snd_ctl_elem_value *ucontrol)
 191{
 192        struct soc_enum *se =
 193                (struct soc_enum *)kcontrol->private_value;
 194        struct snd_sof_control *scontrol = se->dobj.private;
 195        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 196        unsigned int i, channels = scontrol->num_channels;
 197
 198        /* read back each channel */
 199        for (i = 0; i < channels; i++)
 200                ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
 201
 202        return 0;
 203}
 204
 205int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
 206                     struct snd_ctl_elem_value *ucontrol)
 207{
 208        struct soc_enum *se =
 209                (struct soc_enum *)kcontrol->private_value;
 210        struct snd_sof_control *scontrol = se->dobj.private;
 211        struct snd_soc_component *scomp = scontrol->scomp;
 212        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 213        unsigned int i, channels = scontrol->num_channels;
 214        bool change = false;
 215        u32 value;
 216
 217        /* update each channel */
 218        for (i = 0; i < channels; i++) {
 219                value = ucontrol->value.enumerated.item[i];
 220                change = change || (value != cdata->chanv[i].value);
 221                cdata->chanv[i].channel = i;
 222                cdata->chanv[i].value = value;
 223        }
 224
 225        /* notify DSP of enum updates */
 226        if (pm_runtime_active(scomp->dev))
 227                snd_sof_ipc_set_get_comp_data(scontrol,
 228                                              SOF_IPC_COMP_SET_VALUE,
 229                                              SOF_CTRL_TYPE_VALUE_CHAN_GET,
 230                                              SOF_CTRL_CMD_ENUM,
 231                                              true);
 232
 233        return change;
 234}
 235
 236int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
 237                      struct snd_ctl_elem_value *ucontrol)
 238{
 239        struct soc_bytes_ext *be =
 240                (struct soc_bytes_ext *)kcontrol->private_value;
 241        struct snd_sof_control *scontrol = be->dobj.private;
 242        struct snd_soc_component *scomp = scontrol->scomp;
 243        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 244        struct sof_abi_hdr *data = cdata->data;
 245        size_t size;
 246
 247        if (be->max > sizeof(ucontrol->value.bytes.data)) {
 248                dev_err_ratelimited(scomp->dev,
 249                                    "error: data max %d exceeds ucontrol data array size\n",
 250                                    be->max);
 251                return -EINVAL;
 252        }
 253
 254        /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
 255        if (data->size > be->max - sizeof(*data)) {
 256                dev_err_ratelimited(scomp->dev,
 257                                    "error: %u bytes of control data is invalid, max is %zu\n",
 258                                    data->size, be->max - sizeof(*data));
 259                return -EINVAL;
 260        }
 261
 262        size = data->size + sizeof(*data);
 263
 264        /* copy back to kcontrol */
 265        memcpy(ucontrol->value.bytes.data, data, size);
 266
 267        return 0;
 268}
 269
 270int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
 271                      struct snd_ctl_elem_value *ucontrol)
 272{
 273        struct soc_bytes_ext *be =
 274                (struct soc_bytes_ext *)kcontrol->private_value;
 275        struct snd_sof_control *scontrol = be->dobj.private;
 276        struct snd_soc_component *scomp = scontrol->scomp;
 277        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 278        struct sof_abi_hdr *data = cdata->data;
 279        size_t size;
 280
 281        if (be->max > sizeof(ucontrol->value.bytes.data)) {
 282                dev_err_ratelimited(scomp->dev,
 283                                    "error: data max %d exceeds ucontrol data array size\n",
 284                                    be->max);
 285                return -EINVAL;
 286        }
 287
 288        /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
 289        if (data->size > be->max - sizeof(*data)) {
 290                dev_err_ratelimited(scomp->dev,
 291                                    "error: data size too big %u bytes max is %zu\n",
 292                                    data->size, be->max - sizeof(*data));
 293                return -EINVAL;
 294        }
 295
 296        size = data->size + sizeof(*data);
 297
 298        /* copy from kcontrol */
 299        memcpy(data, ucontrol->value.bytes.data, size);
 300
 301        /* notify DSP of byte control updates */
 302        if (pm_runtime_active(scomp->dev))
 303                snd_sof_ipc_set_get_comp_data(scontrol,
 304                                              SOF_IPC_COMP_SET_DATA,
 305                                              SOF_CTRL_TYPE_DATA_SET,
 306                                              scontrol->cmd,
 307                                              true);
 308
 309        return 0;
 310}
 311
 312int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
 313                          const unsigned int __user *binary_data,
 314                          unsigned int size)
 315{
 316        struct soc_bytes_ext *be =
 317                (struct soc_bytes_ext *)kcontrol->private_value;
 318        struct snd_sof_control *scontrol = be->dobj.private;
 319        struct snd_soc_component *scomp = scontrol->scomp;
 320        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 321        struct snd_ctl_tlv header;
 322        const struct snd_ctl_tlv __user *tlvd =
 323                (const struct snd_ctl_tlv __user *)binary_data;
 324
 325        /* make sure we have at least a header */
 326        if (size < sizeof(struct snd_ctl_tlv))
 327                return -EINVAL;
 328
 329        /*
 330         * The beginning of bytes data contains a header from where
 331         * the length (as bytes) is needed to know the correct copy
 332         * length of data from tlvd->tlv.
 333         */
 334        if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv)))
 335                return -EFAULT;
 336
 337        /* make sure TLV info is consistent */
 338        if (header.length + sizeof(struct snd_ctl_tlv) > size) {
 339                dev_err_ratelimited(scomp->dev, "error: inconsistent TLV, data %d + header %zu > %d\n",
 340                                    header.length, sizeof(struct snd_ctl_tlv), size);
 341                return -EINVAL;
 342        }
 343
 344        /* be->max is coming from topology */
 345        if (header.length > be->max) {
 346                dev_err_ratelimited(scomp->dev, "error: Bytes data size %d exceeds max %d.\n",
 347                                    header.length, be->max);
 348                return -EINVAL;
 349        }
 350
 351        /* Check that header id matches the command */
 352        if (header.numid != scontrol->cmd) {
 353                dev_err_ratelimited(scomp->dev,
 354                                    "error: incorrect numid %d\n",
 355                                    header.numid);
 356                return -EINVAL;
 357        }
 358
 359        if (copy_from_user(cdata->data, tlvd->tlv, header.length))
 360                return -EFAULT;
 361
 362        if (cdata->data->magic != SOF_ABI_MAGIC) {
 363                dev_err_ratelimited(scomp->dev,
 364                                    "error: Wrong ABI magic 0x%08x.\n",
 365                                    cdata->data->magic);
 366                return -EINVAL;
 367        }
 368
 369        if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
 370                dev_err_ratelimited(scomp->dev, "error: Incompatible ABI version 0x%08x.\n",
 371                                    cdata->data->abi);
 372                return -EINVAL;
 373        }
 374
 375        /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
 376        if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) {
 377                dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n");
 378                return -EINVAL;
 379        }
 380
 381        /* notify DSP of byte control updates */
 382        if (pm_runtime_active(scomp->dev))
 383                snd_sof_ipc_set_get_comp_data(scontrol,
 384                                              SOF_IPC_COMP_SET_DATA,
 385                                              SOF_CTRL_TYPE_DATA_SET,
 386                                              scontrol->cmd,
 387                                              true);
 388
 389        return 0;
 390}
 391
 392int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data,
 393                                   unsigned int size)
 394{
 395        struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
 396        struct snd_sof_control *scontrol = be->dobj.private;
 397        struct snd_soc_component *scomp = scontrol->scomp;
 398        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 399        struct snd_ctl_tlv header;
 400        struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data;
 401        size_t data_size;
 402        int ret;
 403        int err;
 404
 405        /*
 406         * Decrement the limit by ext bytes header size to
 407         * ensure the user space buffer is not exceeded.
 408         */
 409        if (size < sizeof(struct snd_ctl_tlv))
 410                return -ENOSPC;
 411        size -= sizeof(struct snd_ctl_tlv);
 412
 413        ret = pm_runtime_get_sync(scomp->dev);
 414        if (ret < 0 && ret != -EACCES) {
 415                dev_err_ratelimited(scomp->dev, "error: bytes_ext get failed to resume %d\n", ret);
 416                pm_runtime_put_noidle(scomp->dev);
 417                return ret;
 418        }
 419
 420        /* set the ABI header values */
 421        cdata->data->magic = SOF_ABI_MAGIC;
 422        cdata->data->abi = SOF_ABI_VERSION;
 423        /* get all the component data from DSP */
 424        ret = snd_sof_ipc_set_get_comp_data(scontrol, SOF_IPC_COMP_GET_DATA, SOF_CTRL_TYPE_DATA_GET,
 425                                            scontrol->cmd, false);
 426        if (ret < 0)
 427                goto out;
 428
 429        /* check data size doesn't exceed max coming from topology */
 430        if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) {
 431                dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n",
 432                                    cdata->data->size,
 433                                    be->max - sizeof(struct sof_abi_hdr));
 434                ret = -EINVAL;
 435                goto out;
 436        }
 437
 438        data_size = cdata->data->size + sizeof(struct sof_abi_hdr);
 439
 440        /* make sure we don't exceed size provided by user space for data */
 441        if (data_size > size) {
 442                ret = -ENOSPC;
 443                goto out;
 444        }
 445
 446        header.numid = scontrol->cmd;
 447        header.length = data_size;
 448        if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) {
 449                ret = -EFAULT;
 450                goto out;
 451        }
 452
 453        if (copy_to_user(tlvd->tlv, cdata->data, data_size))
 454                ret = -EFAULT;
 455out:
 456        pm_runtime_mark_last_busy(scomp->dev);
 457        err = pm_runtime_put_autosuspend(scomp->dev);
 458        if (err < 0)
 459                dev_err_ratelimited(scomp->dev, "error: bytes_ext get failed to idle %d\n", err);
 460
 461        return ret;
 462}
 463
 464int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
 465                          unsigned int __user *binary_data,
 466                          unsigned int size)
 467{
 468        struct soc_bytes_ext *be =
 469                (struct soc_bytes_ext *)kcontrol->private_value;
 470        struct snd_sof_control *scontrol = be->dobj.private;
 471        struct snd_soc_component *scomp = scontrol->scomp;
 472        struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
 473        struct snd_ctl_tlv header;
 474        struct snd_ctl_tlv __user *tlvd =
 475                (struct snd_ctl_tlv __user *)binary_data;
 476        size_t data_size;
 477
 478        /*
 479         * Decrement the limit by ext bytes header size to
 480         * ensure the user space buffer is not exceeded.
 481         */
 482        if (size < sizeof(struct snd_ctl_tlv))
 483                return -ENOSPC;
 484        size -= sizeof(struct snd_ctl_tlv);
 485
 486        /* set the ABI header values */
 487        cdata->data->magic = SOF_ABI_MAGIC;
 488        cdata->data->abi = SOF_ABI_VERSION;
 489
 490        /* check data size doesn't exceed max coming from topology */
 491        if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) {
 492                dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n",
 493                                    cdata->data->size,
 494                                    be->max - sizeof(struct sof_abi_hdr));
 495                return -EINVAL;
 496        }
 497
 498        data_size = cdata->data->size + sizeof(struct sof_abi_hdr);
 499
 500        /* make sure we don't exceed size provided by user space for data */
 501        if (data_size > size)
 502                return -ENOSPC;
 503
 504        header.numid = scontrol->cmd;
 505        header.length = data_size;
 506        if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv)))
 507                return -EFAULT;
 508
 509        if (copy_to_user(tlvd->tlv, cdata->data, data_size))
 510                return -EFAULT;
 511
 512        return 0;
 513}
 514