linux/sound/soc/soc-utils-test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2// Copyright (C) 2022 Cirrus Logic, Inc. and
   3//                    Cirrus Logic International Semiconductor Ltd.
   4
   5#include <kunit/test.h>
   6#include <linux/module.h>
   7#include <sound/pcm.h>
   8#include <sound/pcm_params.h>
   9#include <sound/soc.h>
  10#include <uapi/sound/asound.h>
  11
  12static const struct {
  13        u32 rate;
  14        snd_pcm_format_t fmt;
  15        u8 channels;
  16        u8 tdm_width;
  17        u8 tdm_slots;
  18        u8 slot_multiple;
  19        u32 bclk;
  20} tdm_params_to_bclk_cases[] = {
  21        /* rate         fmt        channels tdm_width tdm_slots slot_multiple bclk */
  22
  23        /* From params only */
  24        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 1,  0,      0,      0,        128000 },
  25        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 2,  0,      0,      0,        256000 },
  26        {   8000,  SNDRV_PCM_FORMAT_S24_LE, 1,  0,      0,      0,        192000 },
  27        {   8000,  SNDRV_PCM_FORMAT_S24_LE, 2,  0,      0,      0,        384000 },
  28        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 1,  0,      0,      0,        256000 },
  29        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 2,  0,      0,      0,        512000 },
  30        {  44100,  SNDRV_PCM_FORMAT_S16_LE, 1,  0,      0,      0,        705600 },
  31        {  44100,  SNDRV_PCM_FORMAT_S16_LE, 2,  0,      0,      0,       1411200 },
  32        {  44100,  SNDRV_PCM_FORMAT_S24_LE, 1,  0,      0,      0,       1058400 },
  33        {  44100,  SNDRV_PCM_FORMAT_S24_LE, 2,  0,      0,      0,       2116800 },
  34        {  44100,  SNDRV_PCM_FORMAT_S32_LE, 1,  0,      0,      0,       1411200 },
  35        {  44100,  SNDRV_PCM_FORMAT_S32_LE, 2,  0,      0,      0,       2822400 },
  36        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 1,  0,      0,      0,       6144000 },
  37        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 2,  0,      0,      0,      12288000 },
  38        { 384000,  SNDRV_PCM_FORMAT_S24_LE, 1,  0,      0,      0,       9216000 },
  39        { 384000,  SNDRV_PCM_FORMAT_S24_LE, 2,  0,      0,      0,      18432000 },
  40        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 1,  0,      0,      0,      12288000 },
  41        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 2,  0,      0,      0,      24576000 },
  42
  43        /* I2S from params */
  44        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 1,  0,      0,      2,        256000 },
  45        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 2,  0,      0,      2,        256000 },
  46        {   8000,  SNDRV_PCM_FORMAT_S24_LE, 1,  0,      0,      2,        384000 },
  47        {   8000,  SNDRV_PCM_FORMAT_S24_LE, 2,  0,      0,      2,        384000 },
  48        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 1,  0,      0,      2,        512000 },
  49        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 2,  0,      0,      2,        512000 },
  50        {  44100,  SNDRV_PCM_FORMAT_S16_LE, 1,  0,      0,      2,       1411200 },
  51        {  44100,  SNDRV_PCM_FORMAT_S16_LE, 2,  0,      0,      2,       1411200 },
  52        {  44100,  SNDRV_PCM_FORMAT_S24_LE, 1,  0,      0,      2,       2116800 },
  53        {  44100,  SNDRV_PCM_FORMAT_S24_LE, 2,  0,      0,      2,       2116800 },
  54        {  44100,  SNDRV_PCM_FORMAT_S32_LE, 1,  0,      0,      2,       2822400 },
  55        {  44100,  SNDRV_PCM_FORMAT_S32_LE, 2,  0,      0,      2,       2822400 },
  56        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 1,  0,      0,      2,      12288000 },
  57        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 2,  0,      0,      2,      12288000 },
  58        { 384000,  SNDRV_PCM_FORMAT_S24_LE, 1,  0,      0,      2,      18432000 },
  59        { 384000,  SNDRV_PCM_FORMAT_S24_LE, 2,  0,      0,      2,      18432000 },
  60        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 1,  0,      0,      2,      24576000 },
  61        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 2,  0,      0,      2,      24576000 },
  62
  63        /* Fixed 8-slot TDM, other values from params */
  64        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 1,  0,      8,      0,       1024000 },
  65        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 2,  0,      8,      0,       1024000 },
  66        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 3,  0,      8,      0,       1024000 },
  67        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 4,  0,      8,      0,       1024000 },
  68        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 1,  0,      8,      0,       2048000 },
  69        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 2,  0,      8,      0,       2048000 },
  70        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 3,  0,      8,      0,       2048000 },
  71        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 4,  0,      8,      0,       2048000 },
  72        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 1,  0,      8,      0,      49152000 },
  73        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 2,  0,      8,      0,      49152000 },
  74        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 3,  0,      8,      0,      49152000 },
  75        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 4,  0,      8,      0,      49152000 },
  76        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 1,  0,      8,      0,      98304000 },
  77        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 2,  0,      8,      0,      98304000 },
  78        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 3,  0,      8,      0,      98304000 },
  79        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 4,  0,      8,      0,      98304000 },
  80
  81        /* Fixed 32-bit TDM, other values from params */
  82        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 1,  32,     0,      0,        256000 },
  83        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 2,  32,     0,      0,        512000 },
  84        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 3,  32,     0,      0,        768000 },
  85        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 4,  32,     0,      0,       1024000 },
  86        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 1,  32,     0,      0,        256000 },
  87        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 2,  32,     0,      0,        512000 },
  88        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 3,  32,     0,      0,        768000 },
  89        {   8000,  SNDRV_PCM_FORMAT_S32_LE, 4,  32,     0,      0,       1024000 },
  90        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 1,  32,     0,      0,      12288000 },
  91        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 2,  32,     0,      0,      24576000 },
  92        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 3,  32,     0,      0,      36864000 },
  93        { 384000,  SNDRV_PCM_FORMAT_S16_LE, 4,  32,     0,      0,      49152000 },
  94        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 1,  32,     0,      0,      12288000 },
  95        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 2,  32,     0,      0,      24576000 },
  96        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 3,  32,     0,      0,      36864000 },
  97        { 384000,  SNDRV_PCM_FORMAT_S32_LE, 4,  32,     0,      0,      49152000 },
  98
  99        /* Fixed 6-slot 24-bit TDM, other values from params */
 100        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 1,  24,     6,      0,       1152000 },
 101        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 2,  24,     6,      0,       1152000 },
 102        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 3,  24,     6,      0,       1152000 },
 103        {   8000,  SNDRV_PCM_FORMAT_S16_LE, 4,  24,     6,      0,       1152000 },
 104        {   8000,  SNDRV_PCM_FORMAT_S24_LE, 1,  24,     6,      0,       1152000 },
 105        {   8000,  SNDRV_PCM_FORMAT_S24_LE, 2,  24,     6,      0,       1152000 },
 106        {   8000,  SNDRV_PCM_FORMAT_S24_LE, 3,  24,     6,      0,       1152000 },
 107        {   8000,  SNDRV_PCM_FORMAT_S24_LE, 4,  24,     6,      0,       1152000 },
 108        { 192000,  SNDRV_PCM_FORMAT_S16_LE, 1,  24,     6,      0,      27648000 },
 109        { 192000,  SNDRV_PCM_FORMAT_S16_LE, 2,  24,     6,      0,      27648000 },
 110        { 192000,  SNDRV_PCM_FORMAT_S16_LE, 3,  24,     6,      0,      27648000 },
 111        { 192000,  SNDRV_PCM_FORMAT_S16_LE, 4,  24,     6,      0,      27648000 },
 112        { 192000,  SNDRV_PCM_FORMAT_S24_LE, 1,  24,     6,      0,      27648000 },
 113        { 192000,  SNDRV_PCM_FORMAT_S24_LE, 2,  24,     6,      0,      27648000 },
 114        { 192000,  SNDRV_PCM_FORMAT_S24_LE, 3,  24,     6,      0,      27648000 },
 115        { 192000,  SNDRV_PCM_FORMAT_S24_LE, 4,  24,     6,      0,      27648000 },
 116};
 117
 118static void test_tdm_params_to_bclk_one(struct kunit *test,
 119                                        unsigned int rate, snd_pcm_format_t fmt,
 120                                        unsigned int channels,
 121                                        unsigned int tdm_width, unsigned int tdm_slots,
 122                                        unsigned int slot_multiple,
 123                                        unsigned int expected_bclk)
 124{
 125        struct snd_pcm_hw_params params;
 126        int got_bclk;
 127
 128        _snd_pcm_hw_params_any(&params);
 129        snd_mask_none(hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT));
 130        hw_param_interval(&params, SNDRV_PCM_HW_PARAM_RATE)->min = rate;
 131        hw_param_interval(&params, SNDRV_PCM_HW_PARAM_RATE)->max = rate;
 132        hw_param_interval(&params, SNDRV_PCM_HW_PARAM_CHANNELS)->min = channels;
 133        hw_param_interval(&params, SNDRV_PCM_HW_PARAM_CHANNELS)->max = channels;
 134        params_set_format(&params, fmt);
 135
 136        got_bclk = snd_soc_tdm_params_to_bclk(&params, tdm_width, tdm_slots, slot_multiple);
 137        pr_debug("%s: r=%u sb=%u ch=%u tw=%u ts=%u sm=%u expected=%u got=%d\n",
 138                 __func__,
 139                 rate, params_width(&params), channels, tdm_width, tdm_slots, slot_multiple,
 140                 expected_bclk, got_bclk);
 141        KUNIT_ASSERT_EQ(test, expected_bclk, (unsigned int)got_bclk);
 142}
 143
 144static void test_tdm_params_to_bclk(struct kunit *test)
 145{
 146        int i;
 147
 148        for (i = 0; i < ARRAY_SIZE(tdm_params_to_bclk_cases); ++i) {
 149                test_tdm_params_to_bclk_one(test,
 150                                            tdm_params_to_bclk_cases[i].rate,
 151                                            tdm_params_to_bclk_cases[i].fmt,
 152                                            tdm_params_to_bclk_cases[i].channels,
 153                                            tdm_params_to_bclk_cases[i].tdm_width,
 154                                            tdm_params_to_bclk_cases[i].tdm_slots,
 155                                            tdm_params_to_bclk_cases[i].slot_multiple,
 156                                            tdm_params_to_bclk_cases[i].bclk);
 157
 158                if (tdm_params_to_bclk_cases[i].slot_multiple > 0)
 159                        continue;
 160
 161                /* Slot multiple 1 should have the same effect as multiple 0 */
 162                test_tdm_params_to_bclk_one(test,
 163                                            tdm_params_to_bclk_cases[i].rate,
 164                                            tdm_params_to_bclk_cases[i].fmt,
 165                                            tdm_params_to_bclk_cases[i].channels,
 166                                            tdm_params_to_bclk_cases[i].tdm_width,
 167                                            tdm_params_to_bclk_cases[i].tdm_slots,
 168                                            1,
 169                                            tdm_params_to_bclk_cases[i].bclk);
 170        }
 171}
 172
 173static void test_snd_soc_params_to_bclk_one(struct kunit *test,
 174                                            unsigned int rate, snd_pcm_format_t fmt,
 175                                            unsigned int channels,
 176                                            unsigned int expected_bclk)
 177{
 178        struct snd_pcm_hw_params params;
 179        int got_bclk;
 180
 181        _snd_pcm_hw_params_any(&params);
 182        snd_mask_none(hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT));
 183        hw_param_interval(&params, SNDRV_PCM_HW_PARAM_RATE)->min = rate;
 184        hw_param_interval(&params, SNDRV_PCM_HW_PARAM_RATE)->max = rate;
 185        hw_param_interval(&params, SNDRV_PCM_HW_PARAM_CHANNELS)->min = channels;
 186        hw_param_interval(&params, SNDRV_PCM_HW_PARAM_CHANNELS)->max = channels;
 187        params_set_format(&params, fmt);
 188
 189        got_bclk = snd_soc_params_to_bclk(&params);
 190        pr_debug("%s: r=%u sb=%u ch=%u expected=%u got=%d\n",
 191                 __func__,
 192                 rate, params_width(&params), channels, expected_bclk, got_bclk);
 193        KUNIT_ASSERT_EQ(test, expected_bclk, (unsigned int)got_bclk);
 194}
 195
 196static void test_snd_soc_params_to_bclk(struct kunit *test)
 197{
 198        int i;
 199
 200        for (i = 0; i < ARRAY_SIZE(tdm_params_to_bclk_cases); ++i) {
 201                /*
 202                 * snd_soc_params_to_bclk() is all the test cases where
 203                 * snd_pcm_hw_params values are not overridden.
 204                 */
 205                if (tdm_params_to_bclk_cases[i].tdm_width |
 206                    tdm_params_to_bclk_cases[i].tdm_slots |
 207                    tdm_params_to_bclk_cases[i].slot_multiple)
 208                        continue;
 209
 210                test_snd_soc_params_to_bclk_one(test,
 211                                                tdm_params_to_bclk_cases[i].rate,
 212                                                tdm_params_to_bclk_cases[i].fmt,
 213                                                tdm_params_to_bclk_cases[i].channels,
 214                                                tdm_params_to_bclk_cases[i].bclk);
 215        }
 216}
 217
 218static struct kunit_case soc_utils_test_cases[] = {
 219        KUNIT_CASE(test_tdm_params_to_bclk),
 220        KUNIT_CASE(test_snd_soc_params_to_bclk),
 221        {}
 222};
 223
 224static struct kunit_suite soc_utils_test_suite = {
 225        .name = "soc-utils",
 226        .test_cases = soc_utils_test_cases,
 227};
 228
 229kunit_test_suites(&soc_utils_test_suite);
 230
 231MODULE_DESCRIPTION("ASoC soc-utils kunit test");
 232MODULE_LICENSE("GPL");
 233