mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Add KUnit test cases for: - cs35l56_process_xu_properties() which reads the onchip GPIO definitions. - cs35l56_set_fw_name() calls functions to configure and set the GPIOs. - cs35l56_set_fw_name() saves the ID value in cs35l56_priv.speaker_id. - cs35l56_set_fw_name() does not overwrite a speaker ID that was already found some other way. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://patch.msgid.link/20260205164838.1611295-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
640 lines
20 KiB
C
640 lines
20 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
//
|
|
// KUnit test for the Cirrus Logic cs35l56 driver.
|
|
//
|
|
// Copyright (C) 2026 Cirrus Logic, Inc. and
|
|
// Cirrus Logic International Semiconductor Ltd.
|
|
|
|
#include <kunit/resource.h>
|
|
#include <kunit/test.h>
|
|
#include <kunit/static_stub.h>
|
|
#include <linux/efi.h>
|
|
#include <linux/device/faux.h>
|
|
#include <linux/firmware/cirrus/cs_dsp.h>
|
|
#include <linux/firmware/cirrus/wmfw.h>
|
|
#include <linux/module.h>
|
|
#include <linux/overflow.h>
|
|
#include <linux/pci_ids.h>
|
|
#include <linux/property.h>
|
|
#include <linux/seq_buf.h>
|
|
#include <linux/soundwire/sdw.h>
|
|
#include <sound/cs35l56.h>
|
|
#include <sound/cs-amp-lib.h>
|
|
#include "cs35l56.h"
|
|
|
|
KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
|
|
struct faux_device *)
|
|
|
|
KUNIT_DEFINE_ACTION_WRAPPER(software_node_unregister_node_group_wrapper,
|
|
software_node_unregister_node_group,
|
|
const struct software_node * const *)
|
|
|
|
KUNIT_DEFINE_ACTION_WRAPPER(software_node_unregister_wrapper,
|
|
software_node_unregister,
|
|
const struct software_node *)
|
|
|
|
KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper,
|
|
device_remove_software_node,
|
|
struct device *)
|
|
|
|
struct cs35l56_test_priv {
|
|
struct faux_device *amp_dev;
|
|
struct cs35l56_private *cs35l56_priv;
|
|
|
|
const char *ssidexv2;
|
|
|
|
bool read_onchip_spkid_called;
|
|
bool configure_onchip_spkid_pads_called;
|
|
};
|
|
|
|
struct cs35l56_test_param {
|
|
u8 type;
|
|
u8 rev;
|
|
|
|
s32 spkid_gpios[4];
|
|
s32 spkid_pulls[4];
|
|
};
|
|
|
|
static const struct software_node cs35l56_test_dev_sw_node =
|
|
SOFTWARE_NODE("SWD1", NULL, NULL);
|
|
|
|
static const struct software_node cs35l56_test_af01_sw_node =
|
|
SOFTWARE_NODE("AF01", NULL, &cs35l56_test_dev_sw_node);
|
|
|
|
static const struct software_node *cs35l56_test_dev_and_af01_node_group[] = {
|
|
&cs35l56_test_dev_sw_node,
|
|
&cs35l56_test_af01_sw_node,
|
|
NULL
|
|
};
|
|
|
|
static const char *cs35l56_test_devm_get_vendor_specific_variant_id_none(struct device *dev,
|
|
int ssid_vendor,
|
|
int ssid_device)
|
|
{
|
|
return ERR_PTR(-ENOENT);
|
|
}
|
|
|
|
static void cs35l56_test_l56_b0_suffix_sdw(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Set device type info */
|
|
cs35l56->base.type = 0x56;
|
|
cs35l56->base.rev = 0xb0;
|
|
|
|
/* Set the ALSA name prefix */
|
|
cs35l56->component->name_prefix = "AMP1";
|
|
|
|
/* Set SoundWire link and UID number */
|
|
cs35l56->sdw_link_num = 1;
|
|
cs35l56->sdw_unique_id = 5;
|
|
|
|
kunit_activate_static_stub(test,
|
|
cs35l56_test_devm_get_vendor_specific_variant_id_none,
|
|
cs_amp_devm_get_vendor_specific_variant_id);
|
|
|
|
KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
|
|
|
|
/* Priority suffix should be the legacy ALSA prefix */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "AMP1");
|
|
|
|
/* Fallback suffix should be the new SoundWire ID */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
|
|
}
|
|
|
|
static void cs35l56_test_suffix_sdw(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Set the ALSA name prefix */
|
|
cs35l56->component->name_prefix = "AMP1";
|
|
|
|
/* Set SoundWire link and UID number */
|
|
cs35l56->sdw_link_num = 1;
|
|
cs35l56->sdw_unique_id = 5;
|
|
|
|
kunit_activate_static_stub(test,
|
|
cs35l56_test_devm_get_vendor_specific_variant_id_none,
|
|
cs_amp_devm_get_vendor_specific_variant_id);
|
|
|
|
KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
|
|
|
|
/* Suffix should be the SoundWire ID without a fallback */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "l1u5");
|
|
KUNIT_EXPECT_NULL(test, cs35l56->fallback_fw_suffix);
|
|
}
|
|
|
|
static void cs35l56_test_suffix_i2cspi(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Set the ALSA name prefix */
|
|
cs35l56->component->name_prefix = "AMP1";
|
|
|
|
kunit_activate_static_stub(test,
|
|
cs35l56_test_devm_get_vendor_specific_variant_id_none,
|
|
cs_amp_devm_get_vendor_specific_variant_id);
|
|
|
|
KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
|
|
|
|
/* Suffix strings should not be set: use default wm_adsp suffixing */
|
|
KUNIT_EXPECT_NULL(test, cs35l56->dsp.fwf_suffix);
|
|
KUNIT_EXPECT_NULL(test, cs35l56->fallback_fw_suffix);
|
|
}
|
|
|
|
static efi_status_t cs35l56_test_get_efi_ssidexv2(efi_char16_t *name,
|
|
efi_guid_t *guid,
|
|
u32 *returned_attr,
|
|
unsigned long *size,
|
|
void *buf)
|
|
{
|
|
struct kunit *test = kunit_get_current_test();
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
unsigned int len;
|
|
|
|
KUNIT_ASSERT_NOT_NULL(test, priv->ssidexv2);
|
|
len = strlen(priv->ssidexv2);
|
|
|
|
if (*size < len) {
|
|
*size = len;
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
KUNIT_ASSERT_NOT_NULL(test, buf);
|
|
memcpy(buf, priv->ssidexv2, len);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
static void cs35l56_test_ssidexv2_suffix_sdw(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Set the ALSA name prefix */
|
|
cs35l56->component->name_prefix = "AMP1";
|
|
|
|
/* Set SoundWire link and UID number */
|
|
cs35l56->sdw_link_num = 1;
|
|
cs35l56->sdw_unique_id = 5;
|
|
|
|
/* Set a SSID to enable lookup of SSIDExV2 */
|
|
snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
|
|
|
|
priv->ssidexv2 = "10281234_01_BB_CC";
|
|
|
|
kunit_activate_static_stub(test,
|
|
cs_amp_test_hooks->get_efi_variable,
|
|
cs35l56_test_get_efi_ssidexv2);
|
|
|
|
KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
|
|
|
|
/* Priority suffix should be the SSIDExV2 string with SoundWire ID */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "01-l1u5");
|
|
|
|
/* Fallback suffix should be the SoundWireID */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
|
|
}
|
|
|
|
static void cs35l56_test_ssidexv2_suffix_i2cspi(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Set the ALSA name prefix */
|
|
cs35l56->component->name_prefix = "AMP1";
|
|
|
|
/* Set a SSID to enable lookup of SSIDExV2 */
|
|
snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
|
|
|
|
priv->ssidexv2 = "10281234_01_BB_CC";
|
|
|
|
kunit_activate_static_stub(test,
|
|
cs_amp_test_hooks->get_efi_variable,
|
|
cs35l56_test_get_efi_ssidexv2);
|
|
|
|
KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
|
|
|
|
/* Priority suffix should be the SSIDExV2 string with ALSA name prefix */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "01-AMP1");
|
|
|
|
/* Fallback suffix should be the ALSA name prefix */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "AMP1");
|
|
}
|
|
|
|
/*
|
|
* CS35L56 B0 SoundWire should ignore any SSIDExV2 suffix. It isn't needed
|
|
* on any products with B0 silicon and would interfere with the fallback
|
|
* to legacy naming convention for early B0-based laptops.
|
|
*/
|
|
static void cs35l56_test_l56_b0_ssidexv2_ignored_suffix_sdw(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Set device type info */
|
|
cs35l56->base.type = 0x56;
|
|
cs35l56->base.rev = 0xb0;
|
|
|
|
/* Set the ALSA name prefix */
|
|
cs35l56->component->name_prefix = "AMP1";
|
|
|
|
/* Set SoundWire link and UID number */
|
|
cs35l56->sdw_link_num = 1;
|
|
cs35l56->sdw_unique_id = 5;
|
|
|
|
/* Set a SSID to enable lookup of SSIDExV2 */
|
|
snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
|
|
|
|
priv->ssidexv2 = "10281234_01_BB_CC";
|
|
|
|
kunit_activate_static_stub(test,
|
|
cs_amp_test_hooks->get_efi_variable,
|
|
cs35l56_test_get_efi_ssidexv2);
|
|
|
|
KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
|
|
|
|
/* Priority suffix should be the legacy ALSA prefix */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "AMP1");
|
|
|
|
/* Fallback suffix should be the new SoundWire ID */
|
|
KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
|
|
}
|
|
|
|
/*
|
|
* Test that cs35l56_process_xu_properties() correctly parses the GPIO and
|
|
* pull values from properties into the arrays in struct cs35l56_base.
|
|
*
|
|
* This test creates the node tree:
|
|
*
|
|
* Node("SWD1") { // top-level device node
|
|
* Node("AF01") {
|
|
* Node("mipi-sdca-function-expansion-subproperties") {
|
|
* property: "01fa-spk-id-gpios-onchip"
|
|
* property: 01fa-spk-id-gpios-onchip-pull
|
|
* }
|
|
* }
|
|
* }
|
|
*
|
|
* Note that in ACPI "mipi-sdca-function-expansion-subproperties" is
|
|
* a special _DSD property that points to a Device(EXT0) node but behaves
|
|
* as an alias of the EXT0 node. The equivalent in software nodes is to
|
|
* create a Node named "mipi-sdca-function-expansion-subproperties" with
|
|
* the properties.
|
|
*
|
|
*/
|
|
static void cs35l56_test_parse_xu_onchip_spkid(struct kunit *test)
|
|
{
|
|
const struct cs35l56_test_param *param = test->param_value;
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
struct software_node *ext0_node;
|
|
int num_gpios = 0;
|
|
int num_pulls = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++, num_gpios++) {
|
|
if (param->spkid_gpios[i] < 0)
|
|
break;
|
|
}
|
|
KUNIT_ASSERT_LE(test, num_gpios, ARRAY_SIZE(cs35l56->base.onchip_spkid_gpios));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++, num_pulls++) {
|
|
if (param->spkid_pulls[i] < 0)
|
|
break;
|
|
}
|
|
KUNIT_ASSERT_LE(test, num_pulls, ARRAY_SIZE(cs35l56->base.onchip_spkid_pulls));
|
|
|
|
const struct property_entry ext0_props[] = {
|
|
PROPERTY_ENTRY_U32_ARRAY_LEN("01fa-spk-id-gpios-onchip",
|
|
param->spkid_gpios, num_gpios),
|
|
PROPERTY_ENTRY_U32_ARRAY_LEN("01fa-spk-id-gpios-onchip-pull",
|
|
param->spkid_pulls, num_pulls),
|
|
{ }
|
|
};
|
|
|
|
KUNIT_ASSERT_EQ(test,
|
|
software_node_register_node_group(cs35l56_test_dev_and_af01_node_group),
|
|
0);
|
|
KUNIT_ASSERT_EQ(test,
|
|
kunit_add_action_or_reset(test,
|
|
software_node_unregister_node_group_wrapper,
|
|
cs35l56_test_dev_and_af01_node_group),
|
|
0);
|
|
|
|
ext0_node = kunit_kzalloc(test, sizeof(*ext0_node), GFP_KERNEL);
|
|
KUNIT_ASSERT_NOT_NULL(test, ext0_node);
|
|
*ext0_node = SOFTWARE_NODE("mipi-sdca-function-expansion-subproperties",
|
|
ext0_props, &cs35l56_test_af01_sw_node);
|
|
|
|
KUNIT_ASSERT_EQ(test, software_node_register(ext0_node), 0);
|
|
KUNIT_ASSERT_EQ(test,
|
|
kunit_add_action_or_reset(test,
|
|
software_node_unregister_wrapper,
|
|
ext0_node),
|
|
0);
|
|
|
|
KUNIT_ASSERT_EQ(test,
|
|
device_add_software_node(cs35l56->base.dev, &cs35l56_test_dev_sw_node), 0);
|
|
KUNIT_ASSERT_EQ(test, 0,
|
|
kunit_add_action_or_reset(test,
|
|
device_remove_software_node_wrapper,
|
|
cs35l56->base.dev));
|
|
|
|
KUNIT_EXPECT_EQ(test, cs35l56_process_xu_properties(cs35l56), 0);
|
|
|
|
KUNIT_EXPECT_EQ(test, cs35l56->base.num_onchip_spkid_gpios, num_gpios);
|
|
KUNIT_EXPECT_EQ(test, cs35l56->base.num_onchip_spkid_pulls, num_pulls);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
|
|
if (param->spkid_gpios[i] < 0)
|
|
break;
|
|
|
|
/*
|
|
* cs35l56_process_xu_properties() stores the GPIO numbers
|
|
* zero-based, which is one less than the value in the property.
|
|
*/
|
|
KUNIT_EXPECT_EQ_MSG(test, cs35l56->base.onchip_spkid_gpios[i],
|
|
param->spkid_gpios[i] - 1,
|
|
"i=%d", i);
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) {
|
|
if (param->spkid_pulls[i] < 0)
|
|
break;
|
|
|
|
KUNIT_EXPECT_EQ_MSG(test, cs35l56->base.onchip_spkid_pulls[i],
|
|
param->spkid_pulls[i], "i=%d", i);
|
|
}
|
|
}
|
|
|
|
static int cs35l56_test_dummy_read_onchip_spkid(struct cs35l56_base *cs35l56_base)
|
|
{
|
|
struct kunit *test = kunit_get_current_test();
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
|
|
priv->read_onchip_spkid_called = true;
|
|
|
|
return 4;
|
|
}
|
|
|
|
static int cs35l56_test_dummy_configure_onchip_spkid_pads(struct cs35l56_base *cs35l56_base)
|
|
{
|
|
struct kunit *test = kunit_get_current_test();
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
|
|
priv->configure_onchip_spkid_pads_called = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cs35l56_test_set_fw_name_reads_onchip_spkid(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Provide some on-chip GPIOs for spkid */
|
|
cs35l56->base.onchip_spkid_gpios[0] = 1;
|
|
cs35l56->base.num_onchip_spkid_gpios = 1;
|
|
|
|
cs35l56->speaker_id = -ENOENT;
|
|
|
|
kunit_activate_static_stub(test,
|
|
cs35l56_configure_onchip_spkid_pads,
|
|
cs35l56_test_dummy_configure_onchip_spkid_pads);
|
|
kunit_activate_static_stub(test,
|
|
cs35l56_read_onchip_spkid,
|
|
cs35l56_test_dummy_read_onchip_spkid);
|
|
|
|
priv->configure_onchip_spkid_pads_called = false;
|
|
priv->read_onchip_spkid_called = false;
|
|
KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
|
|
KUNIT_EXPECT_TRUE(test, priv->configure_onchip_spkid_pads_called);
|
|
KUNIT_EXPECT_TRUE(test, priv->read_onchip_spkid_called);
|
|
KUNIT_EXPECT_EQ(test, cs35l56->speaker_id,
|
|
cs35l56_test_dummy_read_onchip_spkid(&cs35l56->base));
|
|
}
|
|
|
|
static void cs35l56_test_set_fw_name_preserves_spkid_with_onchip_gpios(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Provide some on-chip GPIOs for spkid */
|
|
cs35l56->base.onchip_spkid_gpios[0] = 1;
|
|
cs35l56->base.num_onchip_spkid_gpios = 1;
|
|
|
|
/* Simulate that the driver already got a spkid from somewhere */
|
|
cs35l56->speaker_id = 15;
|
|
|
|
KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
|
|
KUNIT_EXPECT_EQ(test, cs35l56->speaker_id, 15);
|
|
}
|
|
|
|
static void cs35l56_test_set_fw_name_preserves_spkid_without_onchip_gpios(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv = test->priv;
|
|
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
|
|
|
|
cs35l56->base.num_onchip_spkid_gpios = 0;
|
|
|
|
/* Simulate that the driver already got a spkid from somewhere */
|
|
cs35l56->speaker_id = 15;
|
|
|
|
KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
|
|
KUNIT_EXPECT_EQ(test, cs35l56->speaker_id, 15);
|
|
}
|
|
|
|
static int cs35l56_test_case_init_common(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv;
|
|
const struct cs35l56_test_param *param = test->param_value;
|
|
struct cs35l56_private *cs35l56;
|
|
|
|
KUNIT_ASSERT_NOT_NULL(test, cs_amp_test_hooks);
|
|
|
|
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
|
|
if (!priv)
|
|
return -ENOMEM;
|
|
|
|
test->priv = priv;
|
|
|
|
/* Create dummy amp driver dev */
|
|
priv->amp_dev = faux_device_create("cs35l56_test_drv", NULL, NULL);
|
|
KUNIT_ASSERT_NOT_NULL(test, priv->amp_dev);
|
|
KUNIT_ASSERT_EQ(test, 0,
|
|
kunit_add_action_or_reset(test,
|
|
faux_device_destroy_wrapper,
|
|
priv->amp_dev));
|
|
|
|
/* Construct minimal set of driver structs */
|
|
priv->cs35l56_priv = kunit_kzalloc(test, sizeof(*priv->cs35l56_priv), GFP_KERNEL);
|
|
KUNIT_ASSERT_NOT_NULL(test, priv->cs35l56_priv);
|
|
cs35l56 = priv->cs35l56_priv;
|
|
cs35l56->base.dev = &priv->amp_dev->dev;
|
|
|
|
cs35l56->component = kunit_kzalloc(test, sizeof(*cs35l56->component), GFP_KERNEL);
|
|
KUNIT_ASSERT_NOT_NULL(test, cs35l56->component);
|
|
cs35l56->component->dev = cs35l56->base.dev;
|
|
snd_soc_component_set_drvdata(cs35l56->component, cs35l56);
|
|
|
|
cs35l56->component->card = kunit_kzalloc(test, sizeof(*cs35l56->component->card),
|
|
GFP_KERNEL);
|
|
KUNIT_ASSERT_NOT_NULL(test, cs35l56->component->card);
|
|
|
|
if (param) {
|
|
cs35l56->base.type = param->type;
|
|
cs35l56->base.rev = param->rev;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cs35l56_test_case_init_soundwire(struct kunit *test)
|
|
{
|
|
struct cs35l56_test_priv *priv;
|
|
struct cs35l56_private *cs35l56;
|
|
int ret;
|
|
|
|
ret = cs35l56_test_case_init_common(test);
|
|
if (ret)
|
|
return ret;
|
|
|
|
priv = test->priv;
|
|
cs35l56 = priv->cs35l56_priv;
|
|
|
|
/* Dummy to indicate this is Soundwire */
|
|
cs35l56->sdw_peripheral = kunit_kzalloc(test, sizeof(*cs35l56->sdw_peripheral),
|
|
GFP_KERNEL);
|
|
if (!cs35l56->sdw_peripheral)
|
|
return -ENOMEM;
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void cs35l56_test_gpio_param_desc(const struct cs35l56_test_param *param, char *desc)
|
|
{
|
|
DECLARE_SEQ_BUF(gpios, 1 + (2 * ARRAY_SIZE(param->spkid_gpios)));
|
|
DECLARE_SEQ_BUF(pulls, 1 + (2 * ARRAY_SIZE(param->spkid_pulls)));
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
|
|
if (param->spkid_gpios[i] < 0)
|
|
break;
|
|
|
|
seq_buf_printf(&gpios, "%s%d", (i == 0) ? "" : ",", param->spkid_gpios[i]);
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) {
|
|
if (param->spkid_pulls[i] < 0)
|
|
break;
|
|
|
|
seq_buf_printf(&pulls, "%s%d", (i == 0) ? "" : ",", param->spkid_pulls[i]);
|
|
}
|
|
|
|
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "gpios:{%s} pulls:{%s}",
|
|
seq_buf_str(&gpios), seq_buf_str(&pulls));
|
|
}
|
|
|
|
static const struct cs35l56_test_param cs35l56_test_onchip_spkid_cases[] = {
|
|
{ .spkid_gpios = { 1, -1 }, .spkid_pulls = { 1, -1 }, },
|
|
{ .spkid_gpios = { 1, -1 }, .spkid_pulls = { 2, -1 }, },
|
|
|
|
{ .spkid_gpios = { 7, -1 }, .spkid_pulls = { 1, -1 }, },
|
|
{ .spkid_gpios = { 7, -1 }, .spkid_pulls = { 2, -1 }, },
|
|
|
|
{ .spkid_gpios = { 1, 7, -1 }, .spkid_pulls = { 1, 1, -1 }, },
|
|
{ .spkid_gpios = { 1, 7, -1 }, .spkid_pulls = { 2, 2, -1 }, },
|
|
|
|
{ .spkid_gpios = { 7, 1, -1 }, .spkid_pulls = { 1, 1, -1 }, },
|
|
{ .spkid_gpios = { 7, 1, -1 }, .spkid_pulls = { 2, 2, -1 }, },
|
|
|
|
{ .spkid_gpios = { 3, 7, 1, -1 }, .spkid_pulls = { 1, 1, 1, -1 }, },
|
|
{ .spkid_gpios = { 3, 7, 1, -1 }, .spkid_pulls = { 2, 2, 2, -1 }, },
|
|
};
|
|
KUNIT_ARRAY_PARAM(cs35l56_test_onchip_spkid,
|
|
cs35l56_test_onchip_spkid_cases,
|
|
cs35l56_test_gpio_param_desc);
|
|
|
|
static void cs35l56_test_type_rev_param_desc(const struct cs35l56_test_param *param,
|
|
char *desc)
|
|
{
|
|
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "type: %02x rev: %02x",
|
|
param->type, param->rev);
|
|
}
|
|
|
|
static const struct cs35l56_test_param cs35l56_test_type_rev_ex_b0_param_cases[] = {
|
|
{ .type = 0x56, .rev = 0xb2 },
|
|
{ .type = 0x57, .rev = 0xb2 },
|
|
{ .type = 0x63, .rev = 0xa1 },
|
|
};
|
|
KUNIT_ARRAY_PARAM(cs35l56_test_type_rev_ex_b0, cs35l56_test_type_rev_ex_b0_param_cases,
|
|
cs35l56_test_type_rev_param_desc);
|
|
|
|
|
|
static const struct cs35l56_test_param cs35l56_test_type_rev_all_param_cases[] = {
|
|
{ .type = 0x56, .rev = 0xb0 },
|
|
{ .type = 0x56, .rev = 0xb2 },
|
|
{ .type = 0x57, .rev = 0xb2 },
|
|
{ .type = 0x63, .rev = 0xa1 },
|
|
};
|
|
KUNIT_ARRAY_PARAM(cs35l56_test_type_rev_all, cs35l56_test_type_rev_all_param_cases,
|
|
cs35l56_test_type_rev_param_desc);
|
|
|
|
static struct kunit_case cs35l56_test_cases_soundwire[] = {
|
|
KUNIT_CASE(cs35l56_test_l56_b0_suffix_sdw),
|
|
KUNIT_CASE_PARAM(cs35l56_test_suffix_sdw, cs35l56_test_type_rev_ex_b0_gen_params),
|
|
KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_sdw,
|
|
cs35l56_test_type_rev_ex_b0_gen_params),
|
|
KUNIT_CASE(cs35l56_test_l56_b0_ssidexv2_ignored_suffix_sdw),
|
|
|
|
KUNIT_CASE_PARAM(cs35l56_test_parse_xu_onchip_spkid,
|
|
cs35l56_test_onchip_spkid_gen_params),
|
|
|
|
KUNIT_CASE(cs35l56_test_set_fw_name_reads_onchip_spkid),
|
|
KUNIT_CASE(cs35l56_test_set_fw_name_preserves_spkid_with_onchip_gpios),
|
|
KUNIT_CASE(cs35l56_test_set_fw_name_preserves_spkid_without_onchip_gpios),
|
|
|
|
{ } /* terminator */
|
|
};
|
|
|
|
static struct kunit_case cs35l56_test_cases_not_soundwire[] = {
|
|
KUNIT_CASE_PARAM(cs35l56_test_suffix_i2cspi, cs35l56_test_type_rev_all_gen_params),
|
|
KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_i2cspi,
|
|
cs35l56_test_type_rev_all_gen_params),
|
|
|
|
KUNIT_CASE(cs35l56_test_set_fw_name_reads_onchip_spkid),
|
|
KUNIT_CASE(cs35l56_test_set_fw_name_preserves_spkid_with_onchip_gpios),
|
|
KUNIT_CASE(cs35l56_test_set_fw_name_preserves_spkid_without_onchip_gpios),
|
|
|
|
{ } /* terminator */
|
|
};
|
|
|
|
static struct kunit_suite cs35l56_test_suite_soundwire = {
|
|
.name = "snd-soc-cs35l56-test-soundwire",
|
|
.init = cs35l56_test_case_init_soundwire,
|
|
.test_cases = cs35l56_test_cases_soundwire,
|
|
};
|
|
|
|
static struct kunit_suite cs35l56_test_suite_not_soundwire = {
|
|
.name = "snd-soc-cs35l56-test-not-soundwire",
|
|
.init = cs35l56_test_case_init_common,
|
|
.test_cases = cs35l56_test_cases_not_soundwire,
|
|
};
|
|
|
|
kunit_test_suites(
|
|
&cs35l56_test_suite_soundwire,
|
|
&cs35l56_test_suite_not_soundwire,
|
|
);
|
|
|
|
MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
|
|
MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
|
|
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
|
|
MODULE_DESCRIPTION("KUnit test for Cirrus Logic cs35l56 codec driver");
|
|
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
|
|
MODULE_LICENSE("GPL");
|