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