linux/sound/soc/soc-utils.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// soc-util.c  --  ALSA SoC Audio Layer utility functions
   4//
   5// Copyright 2009 Wolfson Microelectronics PLC.
   6//
   7// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   8//         Liam Girdwood <lrg@slimlogic.co.uk>
   9
  10#include <linux/platform_device.h>
  11#include <linux/export.h>
  12#include <sound/core.h>
  13#include <sound/pcm.h>
  14#include <sound/pcm_params.h>
  15#include <sound/soc.h>
  16
  17int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots)
  18{
  19        return sample_size * channels * tdm_slots;
  20}
  21EXPORT_SYMBOL_GPL(snd_soc_calc_frame_size);
  22
  23int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params)
  24{
  25        int sample_size;
  26
  27        sample_size = snd_pcm_format_width(params_format(params));
  28        if (sample_size < 0)
  29                return sample_size;
  30
  31        return snd_soc_calc_frame_size(sample_size, params_channels(params),
  32                                       1);
  33}
  34EXPORT_SYMBOL_GPL(snd_soc_params_to_frame_size);
  35
  36int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots)
  37{
  38        return fs * snd_soc_calc_frame_size(sample_size, channels, tdm_slots);
  39}
  40EXPORT_SYMBOL_GPL(snd_soc_calc_bclk);
  41
  42int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params)
  43{
  44        int ret;
  45
  46        ret = snd_soc_params_to_frame_size(params);
  47
  48        if (ret > 0)
  49                return ret * params_rate(params);
  50        else
  51                return ret;
  52}
  53EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk);
  54
  55int snd_soc_component_enable_pin(struct snd_soc_component *component,
  56                                 const char *pin)
  57{
  58        struct snd_soc_dapm_context *dapm =
  59                snd_soc_component_get_dapm(component);
  60        char *full_name;
  61        int ret;
  62
  63        if (!component->name_prefix)
  64                return snd_soc_dapm_enable_pin(dapm, pin);
  65
  66        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  67        if (!full_name)
  68                return -ENOMEM;
  69
  70        ret = snd_soc_dapm_enable_pin(dapm, full_name);
  71        kfree(full_name);
  72
  73        return ret;
  74}
  75EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
  76
  77int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
  78                                          const char *pin)
  79{
  80        struct snd_soc_dapm_context *dapm =
  81                snd_soc_component_get_dapm(component);
  82        char *full_name;
  83        int ret;
  84
  85        if (!component->name_prefix)
  86                return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
  87
  88        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
  89        if (!full_name)
  90                return -ENOMEM;
  91
  92        ret = snd_soc_dapm_enable_pin_unlocked(dapm, full_name);
  93        kfree(full_name);
  94
  95        return ret;
  96}
  97EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
  98
  99int snd_soc_component_disable_pin(struct snd_soc_component *component,
 100                                  const char *pin)
 101{
 102        struct snd_soc_dapm_context *dapm =
 103                snd_soc_component_get_dapm(component);
 104        char *full_name;
 105        int ret;
 106
 107        if (!component->name_prefix)
 108                return snd_soc_dapm_disable_pin(dapm, pin);
 109
 110        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
 111        if (!full_name)
 112                return -ENOMEM;
 113
 114        ret = snd_soc_dapm_disable_pin(dapm, full_name);
 115        kfree(full_name);
 116
 117        return ret;
 118}
 119EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
 120
 121int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
 122                                           const char *pin)
 123{
 124        struct snd_soc_dapm_context *dapm =
 125                snd_soc_component_get_dapm(component);
 126        char *full_name;
 127        int ret;
 128
 129        if (!component->name_prefix)
 130                return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
 131
 132        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
 133        if (!full_name)
 134                return -ENOMEM;
 135
 136        ret = snd_soc_dapm_disable_pin_unlocked(dapm, full_name);
 137        kfree(full_name);
 138
 139        return ret;
 140}
 141EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
 142
 143int snd_soc_component_nc_pin(struct snd_soc_component *component,
 144                             const char *pin)
 145{
 146        struct snd_soc_dapm_context *dapm =
 147                snd_soc_component_get_dapm(component);
 148        char *full_name;
 149        int ret;
 150
 151        if (!component->name_prefix)
 152                return snd_soc_dapm_nc_pin(dapm, pin);
 153
 154        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
 155        if (!full_name)
 156                return -ENOMEM;
 157
 158        ret = snd_soc_dapm_nc_pin(dapm, full_name);
 159        kfree(full_name);
 160
 161        return ret;
 162}
 163EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
 164
 165int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
 166                                      const char *pin)
 167{
 168        struct snd_soc_dapm_context *dapm =
 169                snd_soc_component_get_dapm(component);
 170        char *full_name;
 171        int ret;
 172
 173        if (!component->name_prefix)
 174                return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
 175
 176        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
 177        if (!full_name)
 178                return -ENOMEM;
 179
 180        ret = snd_soc_dapm_nc_pin_unlocked(dapm, full_name);
 181        kfree(full_name);
 182
 183        return ret;
 184}
 185EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
 186
 187int snd_soc_component_get_pin_status(struct snd_soc_component *component,
 188                                     const char *pin)
 189{
 190        struct snd_soc_dapm_context *dapm =
 191                snd_soc_component_get_dapm(component);
 192        char *full_name;
 193        int ret;
 194
 195        if (!component->name_prefix)
 196                return snd_soc_dapm_get_pin_status(dapm, pin);
 197
 198        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
 199        if (!full_name)
 200                return -ENOMEM;
 201
 202        ret = snd_soc_dapm_get_pin_status(dapm, full_name);
 203        kfree(full_name);
 204
 205        return ret;
 206}
 207EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
 208
 209int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
 210                                       const char *pin)
 211{
 212        struct snd_soc_dapm_context *dapm =
 213                snd_soc_component_get_dapm(component);
 214        char *full_name;
 215        int ret;
 216
 217        if (!component->name_prefix)
 218                return snd_soc_dapm_force_enable_pin(dapm, pin);
 219
 220        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
 221        if (!full_name)
 222                return -ENOMEM;
 223
 224        ret = snd_soc_dapm_force_enable_pin(dapm, full_name);
 225        kfree(full_name);
 226
 227        return ret;
 228}
 229EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
 230
 231int snd_soc_component_force_enable_pin_unlocked(
 232                                        struct snd_soc_component *component,
 233                                        const char *pin)
 234{
 235        struct snd_soc_dapm_context *dapm =
 236                snd_soc_component_get_dapm(component);
 237        char *full_name;
 238        int ret;
 239
 240        if (!component->name_prefix)
 241                return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
 242
 243        full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
 244        if (!full_name)
 245                return -ENOMEM;
 246
 247        ret = snd_soc_dapm_force_enable_pin_unlocked(dapm, full_name);
 248        kfree(full_name);
 249
 250        return ret;
 251}
 252EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
 253
 254static const struct snd_pcm_hardware dummy_dma_hardware = {
 255        /* Random values to keep userspace happy when checking constraints */
 256        .info                   = SNDRV_PCM_INFO_INTERLEAVED |
 257                                  SNDRV_PCM_INFO_BLOCK_TRANSFER,
 258        .buffer_bytes_max       = 128*1024,
 259        .period_bytes_min       = PAGE_SIZE,
 260        .period_bytes_max       = PAGE_SIZE*2,
 261        .periods_min            = 2,
 262        .periods_max            = 128,
 263};
 264
 265static int dummy_dma_open(struct snd_pcm_substream *substream)
 266{
 267        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 268
 269        /* BE's dont need dummy params */
 270        if (!rtd->dai_link->no_pcm)
 271                snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
 272
 273        return 0;
 274}
 275
 276static const struct snd_pcm_ops snd_dummy_dma_ops = {
 277        .open           = dummy_dma_open,
 278        .ioctl          = snd_pcm_lib_ioctl,
 279};
 280
 281static const struct snd_soc_component_driver dummy_platform = {
 282        .ops = &snd_dummy_dma_ops,
 283};
 284
 285static const struct snd_soc_component_driver dummy_codec = {
 286        .idle_bias_on           = 1,
 287        .use_pmdown_time        = 1,
 288        .endianness             = 1,
 289        .non_legacy_dai_naming  = 1,
 290};
 291
 292#define STUB_RATES      SNDRV_PCM_RATE_8000_192000
 293#define STUB_FORMATS    (SNDRV_PCM_FMTBIT_S8 | \
 294                        SNDRV_PCM_FMTBIT_U8 | \
 295                        SNDRV_PCM_FMTBIT_S16_LE | \
 296                        SNDRV_PCM_FMTBIT_U16_LE | \
 297                        SNDRV_PCM_FMTBIT_S24_LE | \
 298                        SNDRV_PCM_FMTBIT_U24_LE | \
 299                        SNDRV_PCM_FMTBIT_S32_LE | \
 300                        SNDRV_PCM_FMTBIT_U32_LE | \
 301                        SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
 302/*
 303 * The dummy CODEC is only meant to be used in situations where there is no
 304 * actual hardware.
 305 *
 306 * If there is actual hardware even if it does not have a control bus
 307 * the hardware will still have constraints like supported samplerates, etc.
 308 * which should be modelled. And the data flow graph also should be modelled
 309 * using DAPM.
 310 */
 311static struct snd_soc_dai_driver dummy_dai = {
 312        .name = "snd-soc-dummy-dai",
 313        .playback = {
 314                .stream_name    = "Playback",
 315                .channels_min   = 1,
 316                .channels_max   = 384,
 317                .rates          = STUB_RATES,
 318                .formats        = STUB_FORMATS,
 319        },
 320        .capture = {
 321                .stream_name    = "Capture",
 322                .channels_min   = 1,
 323                .channels_max   = 384,
 324                .rates = STUB_RATES,
 325                .formats = STUB_FORMATS,
 326         },
 327};
 328
 329int snd_soc_dai_is_dummy(struct snd_soc_dai *dai)
 330{
 331        if (dai->driver == &dummy_dai)
 332                return 1;
 333        return 0;
 334}
 335
 336static int snd_soc_dummy_probe(struct platform_device *pdev)
 337{
 338        int ret;
 339
 340        ret = devm_snd_soc_register_component(&pdev->dev,
 341                                              &dummy_codec, &dummy_dai, 1);
 342        if (ret < 0)
 343                return ret;
 344
 345        ret = devm_snd_soc_register_component(&pdev->dev, &dummy_platform,
 346                                              NULL, 0);
 347
 348        return ret;
 349}
 350
 351static struct platform_driver soc_dummy_driver = {
 352        .driver = {
 353                .name = "snd-soc-dummy",
 354        },
 355        .probe = snd_soc_dummy_probe,
 356};
 357
 358static struct platform_device *soc_dummy_dev;
 359
 360int __init snd_soc_util_init(void)
 361{
 362        int ret;
 363
 364        soc_dummy_dev =
 365                platform_device_register_simple("snd-soc-dummy", -1, NULL, 0);
 366        if (IS_ERR(soc_dummy_dev))
 367                return PTR_ERR(soc_dummy_dev);
 368
 369        ret = platform_driver_register(&soc_dummy_driver);
 370        if (ret != 0)
 371                platform_device_unregister(soc_dummy_dev);
 372
 373        return ret;
 374}
 375
 376void __exit snd_soc_util_exit(void)
 377{
 378        platform_driver_unregister(&soc_dummy_driver);
 379        platform_device_unregister(soc_dummy_dev);
 380}
 381