File Index
Files and directories
Sign in
FILE

soc-ops-test.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/soc-ops-test.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2// Copyright (C) 2025 Cirrus Logic, Inc. and
  3//                    Cirrus Logic International Semiconductor Ltd.
  4
  5#include <kunit/device.h>
  6#include <kunit/test.h>
  7#include <linux/module.h>
  8#include <linux/regmap.h>
  9#include <linux/string.h>
 10#include <sound/asound.h>
 11#include <sound/control.h>
 12#include <sound/soc.h>
 13#include <sound/soc-component.h>
 14
 15enum soc_ops_test_control_layout {
 16	SOC_OPS_TEST_SINGLE,
 17	SOC_OPS_TEST_DOUBLE,
 18	SOC_OPS_TEST_DOUBLE_R,
 19};
 20
 21#define TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert) \
 22	.mc = { \
 23		.min = xmin, .max = xmax, .platform_max = xpmax, \
 24		.reg = 0, .shift = 0, .sign_bit = xsign, .invert = xinvert, \
 25		.rreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? 1 : 0, \
 26		.rshift = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? 16 : 0, \
 27	}
 28
 29#define TEST_UINFO(clayout, ctype, cmin, cmax) \
 30	.uinfo = { \
 31		.type = SNDRV_CTL_ELEM_TYPE_##ctype, \
 32		.count = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_SINGLE ? 1 : 2, \
 33		.value.integer.min = cmin, \
 34		.value.integer.max = cmax, \
 35	}
 36
 37#define ITEST(cname, clayout, ctype, cfunc, cmin, cmax, \
 38	      xmin, xmax, xpmax, xsign, xinvert) \
 39	{ \
 40		.name = cname, \
 41		.func_name = #cfunc, \
 42		.layout = SOC_OPS_TEST_##clayout, \
 43		.info = snd_soc_info_##cfunc, \
 44		TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert), \
 45		TEST_UINFO(clayout, ctype, cmin, cmax), \
 46	}
 47
 48#define ATEST(clayout, cfunc, cctl, cret, cinit, \
 49	      xmask, xreg, xmin, xmax, xpmax, xsign, xinvert) \
 50	{ \
 51		.func_name = #cfunc, \
 52		.layout = SOC_OPS_TEST_##clayout, \
 53		.put = snd_soc_put_##cfunc, \
 54		.get = snd_soc_get_##cfunc, \
 55		TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert), \
 56		.lctl = cctl, .rctl = cctl, \
 57		.lmask = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? \
 58				(xmask) | (xmask) << 16 : (xmask), \
 59		.rmask = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? (xmask) : 0, \
 60		.init = cinit ? 0xFFFFFFFF : 0x00000000, \
 61		.lreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? \
 62				(xreg) | (xreg) << 16 : (xreg), \
 63		.rreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? (xreg) : 0, \
 64		.ret = cret, \
 65	}
 66
 67struct soc_ops_test_priv {
 68	struct kunit *test;
 69
 70	struct snd_soc_component component;
 71};
 72
 73struct info_test_param {
 74	const char * const name;
 75	const char * const func_name;
 76	enum soc_ops_test_control_layout layout;
 77	struct soc_mixer_control mc;
 78	int (*info)(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *info);
 79
 80	struct snd_ctl_elem_info uinfo;
 81};
 82
 83struct access_test_param {
 84	const char * const func_name;
 85	enum soc_ops_test_control_layout layout;
 86	struct soc_mixer_control mc;
 87	int (*put)(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *value);
 88	int (*get)(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *value);
 89
 90	unsigned int init;
 91	unsigned int lmask;
 92	unsigned int rmask;
 93	unsigned int lreg;
 94	unsigned int rreg;
 95	long lctl;
 96	long rctl;
 97	int ret;
 98};
 99
100static const struct info_test_param all_info_test_params[] = {
101	// Handling of volume control name for types
102	ITEST("Test Control",        SINGLE,   BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 0),
103	ITEST("Test Volume",         SINGLE,   INTEGER, volsw,    0,  1,   0,  1,  0, 0, 0),
104	ITEST("Test Volume Control", SINGLE,   BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 0),
105	ITEST("Test Control",        DOUBLE_R, BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 0),
106	ITEST("Test Volume",         DOUBLE_R, INTEGER, volsw,    0,  1,   0,  1,  0, 0, 0),
107	ITEST("Test Volume Control", DOUBLE_R, BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 0),
108	ITEST("Test Control",        DOUBLE,   BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 0),
109	ITEST("Test Volume",         DOUBLE,   INTEGER, volsw,    0,  1,   0,  1,  0, 0, 0),
110	ITEST("Test Volume Control", DOUBLE,   BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 0),
111	ITEST("Test Control",        SINGLE,   BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 1),
112	ITEST("Test Volume",         SINGLE,   INTEGER, volsw,    0,  1,   0,  1,  0, 0, 1),
113	ITEST("Test Volume Control", SINGLE,   BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 1),
114	ITEST("Test Control",        DOUBLE,   BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 1),
115	ITEST("Test Volume",         DOUBLE,   INTEGER, volsw,    0,  1,   0,  1,  0, 0, 1),
116	ITEST("Test Volume Control", DOUBLE,   BOOLEAN, volsw,    0,  1,   0,  1,  0, 0, 1),
117	ITEST("Test Control",        SINGLE,   INTEGER, volsw,    0,  2,   0,  2,  0, 0, 0),
118	ITEST("Test Volume",         SINGLE,   INTEGER, volsw,    0,  2,   0,  2,  0, 0, 0),
119	ITEST("Test Volume Control", SINGLE,   INTEGER, volsw,    0,  2,   0,  2,  0, 0, 0),
120	ITEST("Test Control",        SINGLE,   INTEGER, volsw,    0,  1,   0,  2,  1, 0, 0),
121	ITEST("Test Volume",         SINGLE,   INTEGER, volsw,    0,  1,   0,  2,  1, 0, 0),
122	ITEST("Test Volume Control", SINGLE,   INTEGER, volsw,    0,  1,   0,  2,  1, 0, 0),
123	// Negative minimums
124	ITEST("Test Control",        SINGLE,   INTEGER, volsw,    0, 20, -10, 10,  0, 4, 0),
125	ITEST("Test Control",        SINGLE,   INTEGER, volsw,    0, 15, -10, 10, 15, 4, 0),
126	ITEST("Test Control",        SINGLE,   INTEGER, volsw,    0, 20, -10, 10,  0, 4, 1),
127	ITEST("Test Control",        SINGLE,   INTEGER, volsw,    0, 15, -10, 10, 15, 4, 1),
128	// SX control volume control naming
129	ITEST("Test Control",        SINGLE,   BOOLEAN, volsw_sx, 0,  1, 0xF,  1,  0, 0, 0),
130	ITEST("Test Volume",         SINGLE,   INTEGER, volsw_sx, 0,  1, 0xF,  1,  0, 0, 0),
131	ITEST("Test Volume Control", SINGLE,   BOOLEAN, volsw_sx, 0,  1, 0xF,  1,  0, 0, 0),
132	ITEST("Test Control",        SINGLE,   INTEGER, volsw_sx, 0,  4, 0xE,  4,  0, 0, 0),
133	ITEST("Test Volume",         SINGLE,   INTEGER, volsw_sx, 0,  4, 0xE,  4,  0, 0, 0),
134	ITEST("Test Volume Control", SINGLE,   INTEGER, volsw_sx, 0,  4, 0xE,  4,  0, 0, 0),
135	ITEST("Test Control",        SINGLE,   INTEGER, volsw_sx, 0,  3, 0xE,  4,  3, 0, 0),
136	ITEST("Test Volume",         SINGLE,   INTEGER, volsw_sx, 0,  3, 0xE,  4,  3, 0, 0),
137	ITEST("Test Volume Control", SINGLE,   INTEGER, volsw_sx, 0,  3, 0xE,  4,  3, 0, 0),
138};
139
140static const struct access_test_param all_access_test_params[] = {
141	// Single positive value controls
142	ATEST(SINGLE,   volsw,     10,   1, false, 0x1F, 0x0A,    0,  20,  0, 0, 0),
143	ATEST(SINGLE,   volsw,      0,   0, false, 0x1F, 0x00,    0,  20,  0, 0, 0),
144	ATEST(SINGLE,   volsw,     20,   1, false, 0x1F, 0x14,    0,  20,  0, 0, 0),
145	ATEST(SINGLE,   volsw,     10,   1, false, 0x1F, 0x0A,    0,  20, 15, 0, 0),
146	ATEST(SINGLE,   volsw,     25, -22, false, 0x1F, 0x00,    0,  20, 15, 0, 0),
147	ATEST(SINGLE,   volsw,     15,   1, false, 0x1F, 0x0F,    0,  20, 15, 0, 0),
148	// Inverted single positive value controls
149	ATEST(SINGLE,   volsw,     10,   1, false, 0x1F, 0x0A,    0,  20,  0, 0, 1),
150	ATEST(SINGLE,   volsw,      0,   1, false, 0x1F, 0x14,    0,  20,  0, 0, 1),
151	ATEST(SINGLE,   volsw,     20,   0, false, 0x1F, 0x00,    0,  20,  0, 0, 1),
152	ATEST(SINGLE,   volsw,     10,   1, false, 0x1F, 0x0A,    0,  20, 15, 0, 1),
153	ATEST(SINGLE,   volsw,     25, -22, false, 0x1F, 0x00,    0,  20, 15, 0, 1),
154	ATEST(SINGLE,   volsw,     15,   1, false, 0x1F, 0x05,    0,  20, 15, 0, 1),
155	ATEST(SINGLE,   volsw,     10,   1, true,  0x1F, 0x0A,    0,  20,  0, 0, 0),
156	ATEST(SINGLE,   volsw,      0,   1, true,  0x1F, 0x00,    0,  20,  0, 0, 0),
157	ATEST(SINGLE,   volsw,     20,   1, true,  0x1F, 0x14,    0,  20,  0, 0, 0),
158	ATEST(SINGLE,   volsw,     10,   1, true,  0x1F, 0x0A,    0,  20, 15, 0, 0),
159	ATEST(SINGLE,   volsw,     25, -22, true,  0x1F, 0x00,    0,  20, 15, 0, 0),
160	ATEST(SINGLE,   volsw,     15,   1, true,  0x1F, 0x0F,    0,  20, 15, 0, 0),
161	// Single negative value controls
162	ATEST(SINGLE,   volsw,     10,   0, false, 0x1F, 0x00,  -10,  10,  0, 4, 0),
163	ATEST(SINGLE,   volsw,      0,   1, false, 0x1F, 0x16,  -10,  10,  0, 4, 0),
164	ATEST(SINGLE,   volsw,     20,   1, false, 0x1F, 0x0A,  -10,  10,  0, 4, 0),
165	ATEST(SINGLE,   volsw,     10,   0, false, 0x1F, 0x00,  -10,  10, 15, 4, 0),
166	ATEST(SINGLE,   volsw,     25, -22, false, 0x1F, 0x00,  -10,  10, 15, 4, 0),
167	ATEST(SINGLE,   volsw,     15,   1, false, 0x1F, 0x05,  -10,  10, 15, 4, 0),
168	// Single non-zero minimum positive value controls
169	ATEST(SINGLE,   volsw,     10,   1, false, 0x1F, 0x14,   10,  30,  0, 0, 0),
170	ATEST(SINGLE,   volsw,      0,   1, false, 0x1F, 0x0A,   10,  30,  0, 0, 0),
171	ATEST(SINGLE,   volsw,     20,   1, false, 0x1F, 0x1E,   10,  30,  0, 0, 0),
172	ATEST(SINGLE,   volsw,     10,   1, false, 0x1F, 0x14,   10,  30, 15, 0, 0),
173	ATEST(SINGLE,   volsw,     25, -22, false, 0x1F, 0x00,   10,  30, 15, 0, 0),
174	ATEST(SINGLE,   volsw,     15,   1, false, 0x1F, 0x19,   10,  30, 15, 0, 0),
175	// Inverted single non-zero minimum positive value controls
176	ATEST(SINGLE,   volsw,     10,   1, false, 0x1F, 0x14,   10,  30,  0, 0, 1),
177	ATEST(SINGLE,   volsw,      0,   1, false, 0x1F, 0x1E,   10,  30,  0, 0, 1),
178	ATEST(SINGLE,   volsw,     20,   1, false, 0x1F, 0x0A,   10,  30,  0, 0, 1),
179	ATEST(SINGLE,   volsw,     10,   1, false, 0x1F, 0x14,   10,  30, 15, 0, 1),
180	ATEST(SINGLE,   volsw,     25, -22, false, 0x1F, 0x00,   10,  30, 15, 0, 1),
181	ATEST(SINGLE,   volsw,     15,   1, false, 0x1F, 0x0F,   10,  30, 15, 0, 1),
182	// Double register positive value controls
183	ATEST(DOUBLE_R, volsw,     10,   1, false, 0x1F, 0x0A,    0,  20,  0, 0, 0),
184	ATEST(DOUBLE_R, volsw,      0,   0, false, 0x1F, 0x00,    0,  20,  0, 0, 0),
185	ATEST(DOUBLE_R, volsw,     20,   1, false, 0x1F, 0x14,    0,  20,  0, 0, 0),
186	ATEST(DOUBLE_R, volsw,     10,   1, false, 0x1F, 0x0A,    0,  20, 15, 0, 0),
187	ATEST(DOUBLE_R, volsw,     25, -22, false, 0x1F, 0x00,    0,  20, 15, 0, 0),
188	ATEST(DOUBLE_R, volsw,     15,   1, false, 0x1F, 0x0F,    0,  20, 15, 0, 0),
189	// Double register negative value controls
190	ATEST(DOUBLE_R, volsw,     10,   0, false, 0x1F, 0x00,  -10,  10,  0, 4, 0),
191	ATEST(DOUBLE_R, volsw,      0,   1, false, 0x1F, 0x16,  -10,  10,  0, 4, 0),
192	ATEST(DOUBLE_R, volsw,     20,   1, false, 0x1F, 0x0A,  -10,  10,  0, 4, 0),
193	ATEST(DOUBLE_R, volsw,     10,   0, false, 0x1F, 0x00,  -10,  10, 15, 4, 0),
194	ATEST(DOUBLE_R, volsw,     25, -22, false, 0x1F, 0x00,  -10,  10, 15, 4, 0),
195	ATEST(DOUBLE_R, volsw,     15,   1, false, 0x1F, 0x05,  -10,  10, 15, 4, 0),
196	ATEST(DOUBLE_R, volsw,     10,   1, true,  0x1F, 0x00,  -10,  10,  0, 4, 0),
197	ATEST(DOUBLE_R, volsw,      0,   1, true,  0x1F, 0x16,  -10,  10,  0, 4, 0),
198	ATEST(DOUBLE_R, volsw,     20,   1, true,  0x1F, 0x0A,  -10,  10,  0, 4, 0),
199	ATEST(DOUBLE_R, volsw,     10,   1, true,  0x1F, 0x00,  -10,  10, 15, 4, 0),
200	ATEST(DOUBLE_R, volsw,     25, -22, true,  0x1F, 0x00,  -10,  10, 15, 4, 0),
201	ATEST(DOUBLE_R, volsw,     15,   1, true,  0x1F, 0x05,  -10,  10, 15, 4, 0),
202	// Inverted double register negative value controls
203	ATEST(DOUBLE_R, volsw,     10,   1, true,  0x1F, 0x00,  -10,  10,  0, 4, 1),
204	ATEST(DOUBLE_R, volsw,      0,   1, true,  0x1F, 0x0A,  -10,  10,  0, 4, 1),
205	ATEST(DOUBLE_R, volsw,     20,   1, true,  0x1F, 0x16,  -10,  10,  0, 4, 1),
206	ATEST(DOUBLE_R, volsw,     10,   1, true,  0x1F, 0x00,  -10,  10, 15, 4, 1),
207	ATEST(DOUBLE_R, volsw,     25, -22, true,  0x1F, 0x00,  -10,  10, 15, 4, 1),
208	ATEST(DOUBLE_R, volsw,     15,   1, true,  0x1F, 0x1B,  -10,  10, 15, 4, 1),
209	// Double register non-zero minimum positive value controls
210	ATEST(DOUBLE_R, volsw,     10,   1, false, 0x1F, 0x14,   10,  30,  0, 0, 0),
211	ATEST(DOUBLE_R, volsw,      0,   1, false, 0x1F, 0x0A,   10,  30,  0, 0, 0),
212	ATEST(DOUBLE_R, volsw,     20,   1, false, 0x1F, 0x1E,   10,  30,  0, 0, 0),
213	ATEST(DOUBLE_R, volsw,     10,   1, false, 0x1F, 0x14,   10,  30, 15, 0, 0),
214	ATEST(DOUBLE_R, volsw,     25, -22, false, 0x1F, 0x00,   10,  30, 15, 0, 0),
215	ATEST(DOUBLE_R, volsw,     15,   1, false, 0x1F, 0x19,   10,  30, 15, 0, 0),
216	// Double shift positive value controls
217	ATEST(DOUBLE,   volsw,     10,   1, false, 0x1F, 0x0A,    0,  20,  0, 0, 0),
218	ATEST(DOUBLE,   volsw,      0,   0, false, 0x1F, 0x00,    0,  20,  0, 0, 0),
219	ATEST(DOUBLE,   volsw,     20,   1, false, 0x1F, 0x14,    0,  20,  0, 0, 0),
220	ATEST(DOUBLE,   volsw,     10,   1, false, 0x1F, 0x0A,    0,  20, 15, 0, 0),
221	ATEST(DOUBLE,   volsw,     25, -22, false, 0x1F, 0x00,    0,  20, 15, 0, 0),
222	ATEST(DOUBLE,   volsw,     15,   1, false, 0x1F, 0x0F,    0,  20, 15, 0, 0),
223	// Double shift negative value controls
224	ATEST(DOUBLE,   volsw,     10,   0, false, 0x1F, 0x00,  -10,  10,  0, 4, 0),
225	ATEST(DOUBLE,   volsw,      0,   1, false, 0x1F, 0x16,  -10,  10,  0, 4, 0),
226	ATEST(DOUBLE,   volsw,     20,   1, false, 0x1F, 0x0A,  -10,  10,  0, 4, 0),
227	ATEST(DOUBLE,   volsw,     10,   0, false, 0x1F, 0x00,  -10,  10, 15, 4, 0),
228	ATEST(DOUBLE,   volsw,     25, -22, false, 0x1F, 0x00,  -10,  10, 15, 4, 0),
229	ATEST(DOUBLE,   volsw,     15,   1, false, 0x1F, 0x05,  -10,  10, 15, 4, 0),
230	// Inverted double shift negative value controls
231	ATEST(DOUBLE,   volsw,     10,   0, false, 0x1F, 0x00,  -10,  10,  0, 4, 1),
232	ATEST(DOUBLE,   volsw,      0,   1, false, 0x1F, 0x0A,  -10,  10,  0, 4, 1),
233	ATEST(DOUBLE,   volsw,     20,   1, false, 0x1F, 0x16,  -10,  10,  0, 4, 1),
234	ATEST(DOUBLE,   volsw,     10,   0, false, 0x1F, 0x00,  -10,  10, 15, 4, 1),
235	ATEST(DOUBLE,   volsw,     25, -22, false, 0x1F, 0x00,  -10,  10, 15, 4, 1),
236	ATEST(DOUBLE,   volsw,     15,   1, false, 0x1F, 0x1B,  -10,  10, 15, 4, 1),
237	// Double shift non-zero minimum positive value controls
238	ATEST(DOUBLE,   volsw,     10,   1, false, 0x1F, 0x14,   10,  30,  0, 0, 0),
239	ATEST(DOUBLE,   volsw,      0,   1, false, 0x1F, 0x0A,   10,  30,  0, 0, 0),
240	ATEST(DOUBLE,   volsw,     20,   1, false, 0x1F, 0x1E,   10,  30,  0, 0, 0),
241	ATEST(DOUBLE,   volsw,     10,   1, false, 0x1F, 0x14,   10,  30, 15, 0, 0),
242	ATEST(DOUBLE,   volsw,     25, -22, false, 0x1F, 0x00,   10,  30, 15, 0, 0),
243	ATEST(DOUBLE,   volsw,     15,   1, false, 0x1F, 0x19,   10,  30, 15, 0, 0),
244	ATEST(DOUBLE,   volsw,     10,   1, true,  0x1F, 0x14,   10,  30,  0, 0, 0),
245	ATEST(DOUBLE,   volsw,      0,   1, true,  0x1F, 0x0A,   10,  30,  0, 0, 0),
246	ATEST(DOUBLE,   volsw,     20,   1, true,  0x1F, 0x1E,   10,  30,  0, 0, 0),
247	ATEST(DOUBLE,   volsw,     10,   1, true,  0x1F, 0x14,   10,  30, 15, 0, 0),
248	ATEST(DOUBLE,   volsw,     25, -22, true,  0x1F, 0x00,   10,  30, 15, 0, 0),
249	ATEST(DOUBLE,   volsw,     15,   1, true,  0x1F, 0x19,   10,  30, 15, 0, 0),
250	// Single SX all values
251	ATEST(SINGLE,   volsw_sx,   0,   1, false,  0xF, 0x0F, 0x0F,   4,  0, 0, 0),
252	ATEST(SINGLE,   volsw_sx,   1,   0, false,  0xF, 0x00, 0x0F,   4,  0, 0, 0),
253	ATEST(SINGLE,   volsw_sx,   2,   1, false,  0xF, 0x01, 0x0F,   4,  0, 0, 0),
254	ATEST(SINGLE,   volsw_sx,   3,   1, false,  0xF, 0x02, 0x0F,   4,  0, 0, 0),
255	ATEST(SINGLE,   volsw_sx,   4,   1, false,  0xF, 0x03, 0x0F,   4,  0, 0, 0),
256	ATEST(SINGLE,   volsw_sx,   5, -22, false,  0xF, 0x00, 0x0F,   4,  0, 0, 0),
257	ATEST(SINGLE,   volsw_sx,   0,   0, true,   0xF, 0x0F, 0x0F,   4,  0, 0, 0),
258	ATEST(SINGLE,   volsw_sx,   1,   1, true,   0xF, 0x00, 0x0F,   4,  0, 0, 0),
259	ATEST(SINGLE,   volsw_sx,   2,   1, true,   0xF, 0x01, 0x0F,   4,  0, 0, 0),
260	ATEST(SINGLE,   volsw_sx,   3,   1, true,   0xF, 0x02, 0x0F,   4,  0, 0, 0),
261	ATEST(SINGLE,   volsw_sx,   4,   1, true,   0xF, 0x03, 0x0F,   4,  0, 0, 0),
262	ATEST(SINGLE,   volsw_sx,   5, -22, true,   0xF, 0x00, 0x0F,   4,  0, 0, 0),
263	// Inverted single SX all values
264	ATEST(SINGLE,   volsw_sx,   0,   1, false, 0x1F, 0x03, 0x0F,   4,  0, 0, 1),
265	ATEST(SINGLE,   volsw_sx,   1,   1, false, 0x1F, 0x02, 0x0F,   4,  0, 0, 1),
266	ATEST(SINGLE,   volsw_sx,   2,   1, false, 0x1F, 0x01, 0x0F,   4,  0, 0, 1),
267	ATEST(SINGLE,   volsw_sx,   3,   0, false, 0x1F, 0x00, 0x0F,   4,  0, 0, 1),
268	ATEST(SINGLE,   volsw_sx,   4,   1, false, 0x1F, 0x0F, 0x0F,   4,  0, 0, 1),
269	ATEST(SINGLE,   volsw_sx,   5, -22, false, 0x1F, 0x00, 0x0F,   4,  0, 0, 1),
270	// Single SX select values
271	ATEST(SINGLE,   volsw_sx,   0,   1, false, 0xFF, 0x88, 0x88, 144,  0, 0, 0),
272	ATEST(SINGLE,   volsw_sx,   1,   1, false, 0xFF, 0x89, 0x88, 144,  0, 0, 0),
273	ATEST(SINGLE,   volsw_sx, 119,   1, false, 0xFF, 0xFF, 0x88, 144,  0, 0, 0),
274	ATEST(SINGLE,   volsw_sx, 120,   0, false, 0xFF, 0x00, 0x88, 144,  0, 0, 0),
275	ATEST(SINGLE,   volsw_sx, 121,   1, false, 0xFF, 0x01, 0x88, 144,  0, 0, 0),
276	ATEST(SINGLE,   volsw_sx, 143,   1, false, 0xFF, 0x17, 0x88, 144,  0, 0, 0),
277	ATEST(SINGLE,   volsw_sx, 144,   1, false, 0xFF, 0x18, 0x88, 144,  0, 0, 0),
278	ATEST(SINGLE,   volsw_sx, 145, -22, false, 0xFF, 0x00, 0x88, 144,  0, 0, 0),
279	ATEST(SINGLE,   volsw_sx,   0,   1, true,  0xFF, 0x88, 0x88, 144,  0, 0, 0),
280	ATEST(SINGLE,   volsw_sx,   1,   1, true,  0xFF, 0x89, 0x88, 144,  0, 0, 0),
281	ATEST(SINGLE,   volsw_sx, 119,   0, true,  0xFF, 0xFF, 0x88, 144,  0, 0, 0),
282	ATEST(SINGLE,   volsw_sx, 120,   1, true,  0xFF, 0x00, 0x88, 144,  0, 0, 0),
283	ATEST(SINGLE,   volsw_sx, 121,   1, true,  0xFF, 0x01, 0x88, 144,  0, 0, 0),
284	ATEST(SINGLE,   volsw_sx, 143,   1, true,  0xFF, 0x17, 0x88, 144,  0, 0, 0),
285	ATEST(SINGLE,   volsw_sx, 144,   1, true,  0xFF, 0x18, 0x88, 144,  0, 0, 0),
286	ATEST(SINGLE,   volsw_sx, 145, -22, true,  0xFF, 0x00, 0x88, 144,  0, 0, 0),
287	// Double shift SX select values
288	ATEST(DOUBLE,   volsw_sx,   0,   1, true,  0xFF, 0x88, 0x88, 144,  0, 0, 0),
289	ATEST(DOUBLE,   volsw_sx,   1,   1, true,  0xFF, 0x89, 0x88, 144,  0, 0, 0),
290	ATEST(DOUBLE,   volsw_sx, 119,   0, true,  0xFF, 0xFF, 0x88, 144,  0, 0, 0),
291	ATEST(DOUBLE,   volsw_sx, 120,   1, true,  0xFF, 0x00, 0x88, 144,  0, 0, 0),
292	ATEST(DOUBLE,   volsw_sx, 121,   1, true,  0xFF, 0x01, 0x88, 144,  0, 0, 0),
293	ATEST(DOUBLE,   volsw_sx, 143,   1, true,  0xFF, 0x17, 0x88, 144,  0, 0, 0),
294	ATEST(DOUBLE,   volsw_sx, 144,   1, true,  0xFF, 0x18, 0x88, 144,  0, 0, 0),
295	ATEST(DOUBLE,   volsw_sx, 145, -22, true,  0xFF, 0x00, 0x88, 144,  0, 0, 0),
296	// Double register SX select values
297	ATEST(DOUBLE_R, volsw_sx,   0,   1, true,  0xFF, 0x88, 0x88, 144,  0, 0, 0),
298	ATEST(DOUBLE_R, volsw_sx,   1,   1, true,  0xFF, 0x89, 0x88, 144,  0, 0, 0),
299	ATEST(DOUBLE_R, volsw_sx, 119,   0, true,  0xFF, 0xFF, 0x88, 144,  0, 0, 0),
300	ATEST(DOUBLE_R, volsw_sx, 120,   1, true,  0xFF, 0x00, 0x88, 144,  0, 0, 0),
301	ATEST(DOUBLE_R, volsw_sx, 121,   1, true,  0xFF, 0x01, 0x88, 144,  0, 0, 0),
302	ATEST(DOUBLE_R, volsw_sx, 143,   1, true,  0xFF, 0x17, 0x88, 144,  0, 0, 0),
303	ATEST(DOUBLE_R, volsw_sx, 144,   1, true,  0xFF, 0x18, 0x88, 144,  0, 0, 0),
304	ATEST(DOUBLE_R, volsw_sx, 145, -22, true,  0xFF, 0x00, 0x88, 144,  0, 0, 0),
305};
306
307static const char *control_type_str(const snd_ctl_elem_type_t type)
308{
309	switch (type) {
310	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
311		return "bool";
312	case SNDRV_CTL_ELEM_TYPE_INTEGER:
313		return "int";
314	default:
315		return "unknown";
316	}
317}
318
319static const char *control_layout_str(const enum soc_ops_test_control_layout layout)
320{
321	switch (layout) {
322	case SOC_OPS_TEST_SINGLE:
323		return "single";
324	case SOC_OPS_TEST_DOUBLE:
325		return "double";
326	case SOC_OPS_TEST_DOUBLE_R:
327		return "double_r";
328	default:
329		return "unknown";
330	}
331};
332
333static int mock_regmap_read(void *context, const void *reg_buf,
334			    const size_t reg_size, void *val_buf,
335			    size_t val_size)
336{
337	struct soc_ops_test_priv *priv = context;
338
339	KUNIT_FAIL(priv->test, "Unexpected bus read");
340
341	return -EIO;
342}
343
344static int mock_regmap_gather_write(void *context,
345				    const void *reg_buf, size_t reg_size,
346				    const void *val_buf, size_t val_size)
347{
348	struct soc_ops_test_priv *priv = context;
349
350	KUNIT_FAIL(priv->test, "Unexpected bus gather_write");
351
352	return -EIO;
353}
354
355static int mock_regmap_write(void *context, const void *val_buf,
356			     size_t val_size)
357{
358	struct soc_ops_test_priv *priv = context;
359
360	KUNIT_FAIL(priv->test, "Unexpected bus write");
361
362	return -EIO;
363}
364
365static const struct regmap_bus mock_regmap_bus = {
366	.read = mock_regmap_read,
367	.write = mock_regmap_write,
368	.gather_write = mock_regmap_gather_write,
369	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
370	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
371};
372
373static const struct regmap_config mock_regmap_config = {
374	.reg_bits = 32,
375	.val_bits = 32,
376	.reg_format_endian = REGMAP_ENDIAN_NATIVE,
377	.val_format_endian = REGMAP_ENDIAN_NATIVE,
378	.max_register = 0x1,
379	.cache_type = REGCACHE_FLAT,
380};
381
382static int soc_ops_test_init(struct kunit *test)
383{
384	struct soc_ops_test_priv *priv;
385	struct regmap *regmap;
386	struct device *dev;
387
388	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
389	if (!priv)
390		return -ENOMEM;
391
392	priv->test = test;
393
394	dev = kunit_device_register(test, "soc_ops_test_drv");
395	if (IS_ERR(dev))
396		return PTR_ERR(dev);
397
398	regmap = devm_regmap_init(dev, &mock_regmap_bus, priv, &mock_regmap_config);
399	if (IS_ERR(regmap))
400		return PTR_ERR(regmap);
401
402	/* No actual hardware, we just use the cache */
403	regcache_cache_only(regmap, true);
404
405	priv->component.dev = dev;
406	priv->component.regmap = regmap;
407	mutex_init(&priv->component.io_mutex);
408
409	test->priv = priv;
410
411	return 0;
412}
413
414static void soc_ops_test_exit(struct kunit *test)
415{
416	struct soc_ops_test_priv *priv = test->priv;
417
418	kunit_device_unregister(test, priv->component.dev);
419}
420
421static void info_test_desc(const struct info_test_param *param, char *desc)
422{
423	snprintf(desc, KUNIT_PARAM_DESC_SIZE,
424		 "%s %s %s: ctl range: %ld->%ld, reg range: %d->%d(%d), sign: %d, inv: %d",
425		 control_layout_str(param->layout), param->func_name,
426		 control_type_str(param->uinfo.type),
427		 param->uinfo.value.integer.min, param->uinfo.value.integer.max,
428		 param->mc.min, param->mc.max, param->mc.platform_max,
429		 param->mc.sign_bit, param->mc.invert);
430}
431
432static void soc_ops_test_info(struct kunit *test)
433{
434	struct soc_ops_test_priv *priv = test->priv;
435	const struct info_test_param *param = test->param_value;
436	const struct snd_ctl_elem_info *target = &param->uinfo;
437	struct snd_ctl_elem_info result;
438	struct snd_kcontrol kctl = {
439		.private_data = &priv->component,
440		.private_value = (unsigned long)&param->mc,
441	};
442	int ret;
443
444	strscpy(kctl.id.name, param->name, sizeof(kctl.id.name));
445
446	ret = param->info(&kctl, &result);
447	KUNIT_ASSERT_FALSE(test, ret);
448
449	KUNIT_EXPECT_EQ(test, result.count, target->count);
450	KUNIT_EXPECT_EQ(test, result.type, target->type);
451	KUNIT_EXPECT_EQ(test, result.value.integer.min, target->value.integer.min);
452	KUNIT_EXPECT_EQ(test, result.value.integer.max, target->value.integer.max);
453}
454
455static void access_test_desc(const struct access_test_param *param, char *desc)
456{
457	if (param->ret < 0) {
458		snprintf(desc, KUNIT_PARAM_DESC_SIZE,
459			 "%s %s: %ld,%ld -> range: %d->%d(%d), sign: %d, inv: %d -> err: %d",
460			 control_layout_str(param->layout), param->func_name,
461			 param->lctl, param->rctl,
462			 param->mc.min, param->mc.max, param->mc.platform_max,
463			 param->mc.sign_bit, param->mc.invert,
464			 param->ret);
465	} else {
466		snprintf(desc, KUNIT_PARAM_DESC_SIZE,
467			 "%s %s: %ld,%ld -> range: %d->%d(%d), sign: %d, inv: %d -> %#x,%#x",
468			 control_layout_str(param->layout), param->func_name,
469			 param->lctl, param->rctl,
470			 param->mc.min, param->mc.max, param->mc.platform_max,
471			 param->mc.sign_bit, param->mc.invert,
472			 param->lreg, param->rreg);
473	}
474}
475
476static void soc_ops_test_access(struct kunit *test)
477{
478	struct soc_ops_test_priv *priv = test->priv;
479	const struct access_test_param *param = test->param_value;
480	struct snd_kcontrol kctl = {
481		.private_data = &priv->component,
482		.private_value = (unsigned long)&param->mc,
483	};
484	unsigned int val;
485	int ret;
486	/* it is too large struct. use kzalloc() */
487	struct snd_ctl_elem_value *result;
488
489	result = kzalloc(sizeof(*result), GFP_KERNEL);
490	if (!result)
491		return;
492
493	ret = regmap_write(priv->component.regmap, 0x0, param->init);
494	KUNIT_ASSERT_FALSE(test, ret);
495	ret = regmap_write(priv->component.regmap, 0x1, param->init);
496	KUNIT_ASSERT_FALSE(test, ret);
497
498	result->value.integer.value[0] = param->lctl;
499	result->value.integer.value[1] = param->rctl;
500
501	ret = param->put(&kctl, result);
502	KUNIT_ASSERT_EQ(test, ret, param->ret);
503	if (ret < 0)
504		goto end;
505
506	ret = regmap_read(priv->component.regmap, 0x0, &val);
507	KUNIT_ASSERT_FALSE(test, ret);
508	KUNIT_EXPECT_EQ(test, val, (param->init & ~param->lmask) | param->lreg);
509
510	ret = regmap_read(priv->component.regmap, 0x1, &val);
511	KUNIT_ASSERT_FALSE(test, ret);
512	KUNIT_EXPECT_EQ(test, val, (param->init & ~param->rmask) | param->rreg);
513
514	result->value.integer.value[0] = 0;
515	result->value.integer.value[1] = 0;
516
517	ret = param->get(&kctl, result);
518	KUNIT_ASSERT_GE(test, ret, 0);
519
520	KUNIT_EXPECT_EQ(test, result->value.integer.value[0], param->lctl);
521	if (param->layout != SOC_OPS_TEST_SINGLE)
522		KUNIT_EXPECT_EQ(test, result->value.integer.value[1], param->rctl);
523	else
524		KUNIT_EXPECT_EQ(test, result->value.integer.value[1], 0);
525end:
526	kfree(result);
527}
528
529KUNIT_ARRAY_PARAM(all_info_tests, all_info_test_params, info_test_desc);
530KUNIT_ARRAY_PARAM(all_access_tests, all_access_test_params, access_test_desc);
531
532static struct kunit_case soc_ops_test_cases[] = {
533	KUNIT_CASE_PARAM(soc_ops_test_info, all_info_tests_gen_params),
534	KUNIT_CASE_PARAM(soc_ops_test_access, all_access_tests_gen_params),
535	{}
536};
537
538static struct kunit_suite soc_ops_test_suite = {
539	.name = "soc-ops",
540	.init = soc_ops_test_init,
541	.exit = soc_ops_test_exit,
542	.test_cases = soc_ops_test_cases,
543};
544
545kunit_test_suites(&soc_ops_test_suite);
546
547MODULE_DESCRIPTION("ASoC soc-ops kunit test");
548MODULE_LICENSE("GPL");
~/ Read-only file preview.