| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- // SPDX-License-Identifier: GPL-2.0-only
- // Copyright (C) 2025 Cirrus Logic, Inc. and
- // Cirrus Logic International Semiconductor Ltd.
- #include <kunit/device.h>
- #include <kunit/test.h>
- #include <linux/module.h>
- #include <linux/regmap.h>
- #include <linux/string.h>
- #include <sound/asound.h>
- #include <sound/control.h>
- #include <sound/soc.h>
- #include <sound/soc-component.h>
- enum soc_ops_test_control_layout {
- SOC_OPS_TEST_SINGLE,
- SOC_OPS_TEST_DOUBLE,
- SOC_OPS_TEST_DOUBLE_R,
- };
- #define TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert) \
- .mc = { \
- .min = xmin, .max = xmax, .platform_max = xpmax, \
- .reg = 0, .shift = 0, .sign_bit = xsign, .invert = xinvert, \
- .rreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? 1 : 0, \
- .rshift = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? 16 : 0, \
- }
- #define TEST_UINFO(clayout, ctype, cmin, cmax) \
- .uinfo = { \
- .type = SNDRV_CTL_ELEM_TYPE_##ctype, \
- .count = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_SINGLE ? 1 : 2, \
- .value.integer.min = cmin, \
- .value.integer.max = cmax, \
- }
- #define ITEST(cname, clayout, ctype, cfunc, cmin, cmax, \
- xmin, xmax, xpmax, xsign, xinvert) \
- { \
- .name = cname, \
- .func_name = #cfunc, \
- .layout = SOC_OPS_TEST_##clayout, \
- .info = snd_soc_info_##cfunc, \
- TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert), \
- TEST_UINFO(clayout, ctype, cmin, cmax), \
- }
- #define ATEST(clayout, cfunc, cctl, cret, cinit, \
- xmask, xreg, xmin, xmax, xpmax, xsign, xinvert) \
- { \
- .func_name = #cfunc, \
- .layout = SOC_OPS_TEST_##clayout, \
- .put = snd_soc_put_##cfunc, \
- .get = snd_soc_get_##cfunc, \
- TEST_MC(clayout, xmin, xmax, xpmax, xsign, xinvert), \
- .lctl = cctl, .rctl = cctl, \
- .lmask = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? \
- (xmask) | (xmask) << 16 : (xmask), \
- .rmask = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? (xmask) : 0, \
- .init = cinit ? 0xFFFFFFFF : 0x00000000, \
- .lreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE ? \
- (xreg) | (xreg) << 16 : (xreg), \
- .rreg = SOC_OPS_TEST_##clayout == SOC_OPS_TEST_DOUBLE_R ? (xreg) : 0, \
- .ret = cret, \
- }
- struct soc_ops_test_priv {
- struct kunit *test;
- struct snd_soc_component component;
- };
- struct info_test_param {
- const char * const name;
- const char * const func_name;
- enum soc_ops_test_control_layout layout;
- struct soc_mixer_control mc;
- int (*info)(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *info);
- struct snd_ctl_elem_info uinfo;
- };
- struct access_test_param {
- const char * const func_name;
- enum soc_ops_test_control_layout layout;
- struct soc_mixer_control mc;
- int (*put)(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *value);
- int (*get)(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *value);
- unsigned int init;
- unsigned int lmask;
- unsigned int rmask;
- unsigned int lreg;
- unsigned int rreg;
- long lctl;
- long rctl;
- int ret;
- };
- static const struct info_test_param all_info_test_params[] = {
- // Handling of volume control name for types
- ITEST("Test Control", SINGLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Volume", SINGLE, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Volume Control", SINGLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Control", DOUBLE_R, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Volume", DOUBLE_R, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Volume Control", DOUBLE_R, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Control", DOUBLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Volume", DOUBLE, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Volume Control", DOUBLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 0),
- ITEST("Test Control", SINGLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 1),
- ITEST("Test Volume", SINGLE, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 1),
- ITEST("Test Volume Control", SINGLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 1),
- ITEST("Test Control", DOUBLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 1),
- ITEST("Test Volume", DOUBLE, INTEGER, volsw, 0, 1, 0, 1, 0, 0, 1),
- ITEST("Test Volume Control", DOUBLE, BOOLEAN, volsw, 0, 1, 0, 1, 0, 0, 1),
- ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 2, 0, 2, 0, 0, 0),
- ITEST("Test Volume", SINGLE, INTEGER, volsw, 0, 2, 0, 2, 0, 0, 0),
- ITEST("Test Volume Control", SINGLE, INTEGER, volsw, 0, 2, 0, 2, 0, 0, 0),
- ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 1, 0, 2, 1, 0, 0),
- ITEST("Test Volume", SINGLE, INTEGER, volsw, 0, 1, 0, 2, 1, 0, 0),
- ITEST("Test Volume Control", SINGLE, INTEGER, volsw, 0, 1, 0, 2, 1, 0, 0),
- // Negative minimums
- ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 20, -10, 10, 0, 4, 0),
- ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 15, -10, 10, 15, 4, 0),
- ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 20, -10, 10, 0, 4, 1),
- ITEST("Test Control", SINGLE, INTEGER, volsw, 0, 15, -10, 10, 15, 4, 1),
- // SX control volume control naming
- ITEST("Test Control", SINGLE, BOOLEAN, volsw_sx, 0, 1, 0xF, 1, 0, 0, 0),
- ITEST("Test Volume", SINGLE, INTEGER, volsw_sx, 0, 1, 0xF, 1, 0, 0, 0),
- ITEST("Test Volume Control", SINGLE, BOOLEAN, volsw_sx, 0, 1, 0xF, 1, 0, 0, 0),
- ITEST("Test Control", SINGLE, INTEGER, volsw_sx, 0, 4, 0xE, 4, 0, 0, 0),
- ITEST("Test Volume", SINGLE, INTEGER, volsw_sx, 0, 4, 0xE, 4, 0, 0, 0),
- ITEST("Test Volume Control", SINGLE, INTEGER, volsw_sx, 0, 4, 0xE, 4, 0, 0, 0),
- ITEST("Test Control", SINGLE, INTEGER, volsw_sx, 0, 3, 0xE, 4, 3, 0, 0),
- ITEST("Test Volume", SINGLE, INTEGER, volsw_sx, 0, 3, 0xE, 4, 3, 0, 0),
- ITEST("Test Volume Control", SINGLE, INTEGER, volsw_sx, 0, 3, 0xE, 4, 3, 0, 0),
- };
- static const struct access_test_param all_access_test_params[] = {
- // Single positive value controls
- ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 0, 0, 0),
- ATEST(SINGLE, volsw, 0, 0, false, 0x1F, 0x00, 0, 20, 0, 0, 0),
- ATEST(SINGLE, volsw, 20, 1, false, 0x1F, 0x14, 0, 20, 0, 0, 0),
- ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 15, 0, 0),
- ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, 0, 20, 15, 0, 0),
- ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x0F, 0, 20, 15, 0, 0),
- // Inverted single positive value controls
- ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 0, 0, 1),
- ATEST(SINGLE, volsw, 0, 1, false, 0x1F, 0x14, 0, 20, 0, 0, 1),
- ATEST(SINGLE, volsw, 20, 0, false, 0x1F, 0x00, 0, 20, 0, 0, 1),
- ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 15, 0, 1),
- ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, 0, 20, 15, 0, 1),
- ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x05, 0, 20, 15, 0, 1),
- ATEST(SINGLE, volsw, 10, 1, true, 0x1F, 0x0A, 0, 20, 0, 0, 0),
- ATEST(SINGLE, volsw, 0, 1, true, 0x1F, 0x00, 0, 20, 0, 0, 0),
- ATEST(SINGLE, volsw, 20, 1, true, 0x1F, 0x14, 0, 20, 0, 0, 0),
- ATEST(SINGLE, volsw, 10, 1, true, 0x1F, 0x0A, 0, 20, 15, 0, 0),
- ATEST(SINGLE, volsw, 25, -22, true, 0x1F, 0x00, 0, 20, 15, 0, 0),
- ATEST(SINGLE, volsw, 15, 1, true, 0x1F, 0x0F, 0, 20, 15, 0, 0),
- // Single negative value controls
- ATEST(SINGLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 0, 4, 0),
- ATEST(SINGLE, volsw, 0, 1, false, 0x1F, 0x16, -10, 10, 0, 4, 0),
- ATEST(SINGLE, volsw, 20, 1, false, 0x1F, 0x0A, -10, 10, 0, 4, 0),
- ATEST(SINGLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 15, 4, 0),
- ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, -10, 10, 15, 4, 0),
- ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x05, -10, 10, 15, 4, 0),
- // Single non-zero minimum positive value controls
- ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 0, 0, 0),
- ATEST(SINGLE, volsw, 0, 1, false, 0x1F, 0x0A, 10, 30, 0, 0, 0),
- ATEST(SINGLE, volsw, 20, 1, false, 0x1F, 0x1E, 10, 30, 0, 0, 0),
- ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 15, 0, 0),
- ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, 10, 30, 15, 0, 0),
- ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x19, 10, 30, 15, 0, 0),
- // Inverted single non-zero minimum positive value controls
- ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 0, 0, 1),
- ATEST(SINGLE, volsw, 0, 1, false, 0x1F, 0x1E, 10, 30, 0, 0, 1),
- ATEST(SINGLE, volsw, 20, 1, false, 0x1F, 0x0A, 10, 30, 0, 0, 1),
- ATEST(SINGLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 15, 0, 1),
- ATEST(SINGLE, volsw, 25, -22, false, 0x1F, 0x00, 10, 30, 15, 0, 1),
- ATEST(SINGLE, volsw, 15, 1, false, 0x1F, 0x0F, 10, 30, 15, 0, 1),
- // Double register positive value controls
- ATEST(DOUBLE_R, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 0, 0, 0),
- ATEST(DOUBLE_R, volsw, 0, 0, false, 0x1F, 0x00, 0, 20, 0, 0, 0),
- ATEST(DOUBLE_R, volsw, 20, 1, false, 0x1F, 0x14, 0, 20, 0, 0, 0),
- ATEST(DOUBLE_R, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 15, 0, 0),
- ATEST(DOUBLE_R, volsw, 25, -22, false, 0x1F, 0x00, 0, 20, 15, 0, 0),
- ATEST(DOUBLE_R, volsw, 15, 1, false, 0x1F, 0x0F, 0, 20, 15, 0, 0),
- // Double register negative value controls
- ATEST(DOUBLE_R, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 0, 4, 0),
- ATEST(DOUBLE_R, volsw, 0, 1, false, 0x1F, 0x16, -10, 10, 0, 4, 0),
- ATEST(DOUBLE_R, volsw, 20, 1, false, 0x1F, 0x0A, -10, 10, 0, 4, 0),
- ATEST(DOUBLE_R, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 15, 4, 0),
- ATEST(DOUBLE_R, volsw, 25, -22, false, 0x1F, 0x00, -10, 10, 15, 4, 0),
- ATEST(DOUBLE_R, volsw, 15, 1, false, 0x1F, 0x05, -10, 10, 15, 4, 0),
- ATEST(DOUBLE_R, volsw, 10, 1, true, 0x1F, 0x00, -10, 10, 0, 4, 0),
- ATEST(DOUBLE_R, volsw, 0, 1, true, 0x1F, 0x16, -10, 10, 0, 4, 0),
- ATEST(DOUBLE_R, volsw, 20, 1, true, 0x1F, 0x0A, -10, 10, 0, 4, 0),
- ATEST(DOUBLE_R, volsw, 10, 1, true, 0x1F, 0x00, -10, 10, 15, 4, 0),
- ATEST(DOUBLE_R, volsw, 25, -22, true, 0x1F, 0x00, -10, 10, 15, 4, 0),
- ATEST(DOUBLE_R, volsw, 15, 1, true, 0x1F, 0x05, -10, 10, 15, 4, 0),
- // Inverted double register negative value controls
- ATEST(DOUBLE_R, volsw, 10, 1, true, 0x1F, 0x00, -10, 10, 0, 4, 1),
- ATEST(DOUBLE_R, volsw, 0, 1, true, 0x1F, 0x0A, -10, 10, 0, 4, 1),
- ATEST(DOUBLE_R, volsw, 20, 1, true, 0x1F, 0x16, -10, 10, 0, 4, 1),
- ATEST(DOUBLE_R, volsw, 10, 1, true, 0x1F, 0x00, -10, 10, 15, 4, 1),
- ATEST(DOUBLE_R, volsw, 25, -22, true, 0x1F, 0x00, -10, 10, 15, 4, 1),
- ATEST(DOUBLE_R, volsw, 15, 1, true, 0x1F, 0x1B, -10, 10, 15, 4, 1),
- // Double register non-zero minimum positive value controls
- ATEST(DOUBLE_R, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 0, 0, 0),
- ATEST(DOUBLE_R, volsw, 0, 1, false, 0x1F, 0x0A, 10, 30, 0, 0, 0),
- ATEST(DOUBLE_R, volsw, 20, 1, false, 0x1F, 0x1E, 10, 30, 0, 0, 0),
- ATEST(DOUBLE_R, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 15, 0, 0),
- ATEST(DOUBLE_R, volsw, 25, -22, false, 0x1F, 0x00, 10, 30, 15, 0, 0),
- ATEST(DOUBLE_R, volsw, 15, 1, false, 0x1F, 0x19, 10, 30, 15, 0, 0),
- // Double shift positive value controls
- ATEST(DOUBLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 0, 0, 0),
- ATEST(DOUBLE, volsw, 0, 0, false, 0x1F, 0x00, 0, 20, 0, 0, 0),
- ATEST(DOUBLE, volsw, 20, 1, false, 0x1F, 0x14, 0, 20, 0, 0, 0),
- ATEST(DOUBLE, volsw, 10, 1, false, 0x1F, 0x0A, 0, 20, 15, 0, 0),
- ATEST(DOUBLE, volsw, 25, -22, false, 0x1F, 0x00, 0, 20, 15, 0, 0),
- ATEST(DOUBLE, volsw, 15, 1, false, 0x1F, 0x0F, 0, 20, 15, 0, 0),
- // Double shift negative value controls
- ATEST(DOUBLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 0, 4, 0),
- ATEST(DOUBLE, volsw, 0, 1, false, 0x1F, 0x16, -10, 10, 0, 4, 0),
- ATEST(DOUBLE, volsw, 20, 1, false, 0x1F, 0x0A, -10, 10, 0, 4, 0),
- ATEST(DOUBLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 15, 4, 0),
- ATEST(DOUBLE, volsw, 25, -22, false, 0x1F, 0x00, -10, 10, 15, 4, 0),
- ATEST(DOUBLE, volsw, 15, 1, false, 0x1F, 0x05, -10, 10, 15, 4, 0),
- // Inverted double shift negative value controls
- ATEST(DOUBLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 0, 4, 1),
- ATEST(DOUBLE, volsw, 0, 1, false, 0x1F, 0x0A, -10, 10, 0, 4, 1),
- ATEST(DOUBLE, volsw, 20, 1, false, 0x1F, 0x16, -10, 10, 0, 4, 1),
- ATEST(DOUBLE, volsw, 10, 0, false, 0x1F, 0x00, -10, 10, 15, 4, 1),
- ATEST(DOUBLE, volsw, 25, -22, false, 0x1F, 0x00, -10, 10, 15, 4, 1),
- ATEST(DOUBLE, volsw, 15, 1, false, 0x1F, 0x1B, -10, 10, 15, 4, 1),
- // Double shift non-zero minimum positive value controls
- ATEST(DOUBLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 0, 0, 0),
- ATEST(DOUBLE, volsw, 0, 1, false, 0x1F, 0x0A, 10, 30, 0, 0, 0),
- ATEST(DOUBLE, volsw, 20, 1, false, 0x1F, 0x1E, 10, 30, 0, 0, 0),
- ATEST(DOUBLE, volsw, 10, 1, false, 0x1F, 0x14, 10, 30, 15, 0, 0),
- ATEST(DOUBLE, volsw, 25, -22, false, 0x1F, 0x00, 10, 30, 15, 0, 0),
- ATEST(DOUBLE, volsw, 15, 1, false, 0x1F, 0x19, 10, 30, 15, 0, 0),
- ATEST(DOUBLE, volsw, 10, 1, true, 0x1F, 0x14, 10, 30, 0, 0, 0),
- ATEST(DOUBLE, volsw, 0, 1, true, 0x1F, 0x0A, 10, 30, 0, 0, 0),
- ATEST(DOUBLE, volsw, 20, 1, true, 0x1F, 0x1E, 10, 30, 0, 0, 0),
- ATEST(DOUBLE, volsw, 10, 1, true, 0x1F, 0x14, 10, 30, 15, 0, 0),
- ATEST(DOUBLE, volsw, 25, -22, true, 0x1F, 0x00, 10, 30, 15, 0, 0),
- ATEST(DOUBLE, volsw, 15, 1, true, 0x1F, 0x19, 10, 30, 15, 0, 0),
- // Single SX all values
- ATEST(SINGLE, volsw_sx, 0, 1, false, 0xF, 0x0F, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 1, 0, false, 0xF, 0x00, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 2, 1, false, 0xF, 0x01, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 3, 1, false, 0xF, 0x02, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 4, 1, false, 0xF, 0x03, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 5, -22, false, 0xF, 0x00, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 0, 0, true, 0xF, 0x0F, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 1, 1, true, 0xF, 0x00, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 2, 1, true, 0xF, 0x01, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 3, 1, true, 0xF, 0x02, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 4, 1, true, 0xF, 0x03, 0x0F, 4, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 5, -22, true, 0xF, 0x00, 0x0F, 4, 0, 0, 0),
- // Inverted single SX all values
- ATEST(SINGLE, volsw_sx, 0, 1, false, 0x1F, 0x03, 0x0F, 4, 0, 0, 1),
- ATEST(SINGLE, volsw_sx, 1, 1, false, 0x1F, 0x02, 0x0F, 4, 0, 0, 1),
- ATEST(SINGLE, volsw_sx, 2, 1, false, 0x1F, 0x01, 0x0F, 4, 0, 0, 1),
- ATEST(SINGLE, volsw_sx, 3, 0, false, 0x1F, 0x00, 0x0F, 4, 0, 0, 1),
- ATEST(SINGLE, volsw_sx, 4, 1, false, 0x1F, 0x0F, 0x0F, 4, 0, 0, 1),
- ATEST(SINGLE, volsw_sx, 5, -22, false, 0x1F, 0x00, 0x0F, 4, 0, 0, 1),
- // Single SX select values
- ATEST(SINGLE, volsw_sx, 0, 1, false, 0xFF, 0x88, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 1, 1, false, 0xFF, 0x89, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 119, 1, false, 0xFF, 0xFF, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 120, 0, false, 0xFF, 0x00, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 121, 1, false, 0xFF, 0x01, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 143, 1, false, 0xFF, 0x17, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 144, 1, false, 0xFF, 0x18, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 145, -22, false, 0xFF, 0x00, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 0, 1, true, 0xFF, 0x88, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 1, 1, true, 0xFF, 0x89, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 119, 0, true, 0xFF, 0xFF, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 120, 1, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 121, 1, true, 0xFF, 0x01, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 143, 1, true, 0xFF, 0x17, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 144, 1, true, 0xFF, 0x18, 0x88, 144, 0, 0, 0),
- ATEST(SINGLE, volsw_sx, 145, -22, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0),
- // Double shift SX select values
- ATEST(DOUBLE, volsw_sx, 0, 1, true, 0xFF, 0x88, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE, volsw_sx, 1, 1, true, 0xFF, 0x89, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE, volsw_sx, 119, 0, true, 0xFF, 0xFF, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE, volsw_sx, 120, 1, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE, volsw_sx, 121, 1, true, 0xFF, 0x01, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE, volsw_sx, 143, 1, true, 0xFF, 0x17, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE, volsw_sx, 144, 1, true, 0xFF, 0x18, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE, volsw_sx, 145, -22, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0),
- // Double register SX select values
- ATEST(DOUBLE_R, volsw_sx, 0, 1, true, 0xFF, 0x88, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE_R, volsw_sx, 1, 1, true, 0xFF, 0x89, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE_R, volsw_sx, 119, 0, true, 0xFF, 0xFF, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE_R, volsw_sx, 120, 1, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE_R, volsw_sx, 121, 1, true, 0xFF, 0x01, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE_R, volsw_sx, 143, 1, true, 0xFF, 0x17, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE_R, volsw_sx, 144, 1, true, 0xFF, 0x18, 0x88, 144, 0, 0, 0),
- ATEST(DOUBLE_R, volsw_sx, 145, -22, true, 0xFF, 0x00, 0x88, 144, 0, 0, 0),
- };
- static const char *control_type_str(const snd_ctl_elem_type_t type)
- {
- switch (type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- return "bool";
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- return "int";
- default:
- return "unknown";
- }
- }
- static const char *control_layout_str(const enum soc_ops_test_control_layout layout)
- {
- switch (layout) {
- case SOC_OPS_TEST_SINGLE:
- return "single";
- case SOC_OPS_TEST_DOUBLE:
- return "double";
- case SOC_OPS_TEST_DOUBLE_R:
- return "double_r";
- default:
- return "unknown";
- }
- };
- static int mock_regmap_read(void *context, const void *reg_buf,
- const size_t reg_size, void *val_buf,
- size_t val_size)
- {
- struct soc_ops_test_priv *priv = context;
- KUNIT_FAIL(priv->test, "Unexpected bus read");
- return -EIO;
- }
- static int mock_regmap_gather_write(void *context,
- const void *reg_buf, size_t reg_size,
- const void *val_buf, size_t val_size)
- {
- struct soc_ops_test_priv *priv = context;
- KUNIT_FAIL(priv->test, "Unexpected bus gather_write");
- return -EIO;
- }
- static int mock_regmap_write(void *context, const void *val_buf,
- size_t val_size)
- {
- struct soc_ops_test_priv *priv = context;
- KUNIT_FAIL(priv->test, "Unexpected bus write");
- return -EIO;
- }
- static const struct regmap_bus mock_regmap_bus = {
- .read = mock_regmap_read,
- .write = mock_regmap_write,
- .gather_write = mock_regmap_gather_write,
- .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
- .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
- };
- static const struct regmap_config mock_regmap_config = {
- .reg_bits = 32,
- .val_bits = 32,
- .reg_format_endian = REGMAP_ENDIAN_NATIVE,
- .val_format_endian = REGMAP_ENDIAN_NATIVE,
- .max_register = 0x1,
- .cache_type = REGCACHE_FLAT,
- };
- static int soc_ops_test_init(struct kunit *test)
- {
- struct soc_ops_test_priv *priv;
- struct regmap *regmap;
- struct device *dev;
- priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- priv->test = test;
- dev = kunit_device_register(test, "soc_ops_test_drv");
- if (IS_ERR(dev))
- return PTR_ERR(dev);
- regmap = devm_regmap_init(dev, &mock_regmap_bus, priv, &mock_regmap_config);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
- /* No actual hardware, we just use the cache */
- regcache_cache_only(regmap, true);
- priv->component.dev = dev;
- priv->component.regmap = regmap;
- mutex_init(&priv->component.io_mutex);
- test->priv = priv;
- return 0;
- }
- static void soc_ops_test_exit(struct kunit *test)
- {
- struct soc_ops_test_priv *priv = test->priv;
- kunit_device_unregister(test, priv->component.dev);
- }
- static void info_test_desc(const struct info_test_param *param, char *desc)
- {
- snprintf(desc, KUNIT_PARAM_DESC_SIZE,
- "%s %s %s: ctl range: %ld->%ld, reg range: %d->%d(%d), sign: %d, inv: %d",
- control_layout_str(param->layout), param->func_name,
- control_type_str(param->uinfo.type),
- param->uinfo.value.integer.min, param->uinfo.value.integer.max,
- param->mc.min, param->mc.max, param->mc.platform_max,
- param->mc.sign_bit, param->mc.invert);
- }
- static void soc_ops_test_info(struct kunit *test)
- {
- struct soc_ops_test_priv *priv = test->priv;
- const struct info_test_param *param = test->param_value;
- const struct snd_ctl_elem_info *target = ¶m->uinfo;
- struct snd_ctl_elem_info result;
- struct snd_kcontrol kctl = {
- .private_data = &priv->component,
- .private_value = (unsigned long)¶m->mc,
- };
- int ret;
- strscpy(kctl.id.name, param->name, sizeof(kctl.id.name));
- ret = param->info(&kctl, &result);
- KUNIT_ASSERT_FALSE(test, ret);
- KUNIT_EXPECT_EQ(test, result.count, target->count);
- KUNIT_EXPECT_EQ(test, result.type, target->type);
- KUNIT_EXPECT_EQ(test, result.value.integer.min, target->value.integer.min);
- KUNIT_EXPECT_EQ(test, result.value.integer.max, target->value.integer.max);
- }
- static void access_test_desc(const struct access_test_param *param, char *desc)
- {
- if (param->ret < 0) {
- snprintf(desc, KUNIT_PARAM_DESC_SIZE,
- "%s %s: %ld,%ld -> range: %d->%d(%d), sign: %d, inv: %d -> err: %d",
- control_layout_str(param->layout), param->func_name,
- param->lctl, param->rctl,
- param->mc.min, param->mc.max, param->mc.platform_max,
- param->mc.sign_bit, param->mc.invert,
- param->ret);
- } else {
- snprintf(desc, KUNIT_PARAM_DESC_SIZE,
- "%s %s: %ld,%ld -> range: %d->%d(%d), sign: %d, inv: %d -> %#x,%#x",
- control_layout_str(param->layout), param->func_name,
- param->lctl, param->rctl,
- param->mc.min, param->mc.max, param->mc.platform_max,
- param->mc.sign_bit, param->mc.invert,
- param->lreg, param->rreg);
- }
- }
- static void soc_ops_test_access(struct kunit *test)
- {
- struct soc_ops_test_priv *priv = test->priv;
- const struct access_test_param *param = test->param_value;
- struct snd_kcontrol kctl = {
- .private_data = &priv->component,
- .private_value = (unsigned long)¶m->mc,
- };
- unsigned int val;
- int ret;
- /* it is too large struct. use kzalloc() */
- struct snd_ctl_elem_value *result;
- result = kzalloc_obj(*result);
- if (!result)
- return;
- ret = regmap_write(priv->component.regmap, 0x0, param->init);
- KUNIT_ASSERT_FALSE(test, ret);
- ret = regmap_write(priv->component.regmap, 0x1, param->init);
- KUNIT_ASSERT_FALSE(test, ret);
- result->value.integer.value[0] = param->lctl;
- result->value.integer.value[1] = param->rctl;
- ret = param->put(&kctl, result);
- KUNIT_ASSERT_EQ(test, ret, param->ret);
- if (ret < 0)
- goto end;
- ret = regmap_read(priv->component.regmap, 0x0, &val);
- KUNIT_ASSERT_FALSE(test, ret);
- KUNIT_EXPECT_EQ(test, val, (param->init & ~param->lmask) | param->lreg);
- ret = regmap_read(priv->component.regmap, 0x1, &val);
- KUNIT_ASSERT_FALSE(test, ret);
- KUNIT_EXPECT_EQ(test, val, (param->init & ~param->rmask) | param->rreg);
- result->value.integer.value[0] = 0;
- result->value.integer.value[1] = 0;
- ret = param->get(&kctl, result);
- KUNIT_ASSERT_GE(test, ret, 0);
- KUNIT_EXPECT_EQ(test, result->value.integer.value[0], param->lctl);
- if (param->layout != SOC_OPS_TEST_SINGLE)
- KUNIT_EXPECT_EQ(test, result->value.integer.value[1], param->rctl);
- else
- KUNIT_EXPECT_EQ(test, result->value.integer.value[1], 0);
- end:
- kfree(result);
- }
- KUNIT_ARRAY_PARAM(all_info_tests, all_info_test_params, info_test_desc);
- KUNIT_ARRAY_PARAM(all_access_tests, all_access_test_params, access_test_desc);
- static struct kunit_case soc_ops_test_cases[] = {
- KUNIT_CASE_PARAM(soc_ops_test_info, all_info_tests_gen_params),
- KUNIT_CASE_PARAM(soc_ops_test_access, all_access_tests_gen_params),
- {}
- };
- static struct kunit_suite soc_ops_test_suite = {
- .name = "soc-ops",
- .init = soc_ops_test_init,
- .exit = soc_ops_test_exit,
- .test_cases = soc_ops_test_cases,
- };
- kunit_test_suites(&soc_ops_test_suite);
- MODULE_DESCRIPTION("ASoC soc-ops kunit test");
- MODULE_LICENSE("GPL");
|