Unverified Commit be9d8d96 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: cs35l56: Add support for new Dell laptops

Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>:

On new Dell models the driver must read a UEFI variable to get a
variant identifier for the audio hardware. Without this, the driver
cannot know which firmware file to load to the amps.
parents 7f428282 d0ab8995
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@ int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_
int cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, int num_amps,
				    const struct cirrus_amp_cal_data *in_data);
int cs_amp_get_vendor_spkid(struct device *dev);
const char *cs_amp_devm_get_vendor_specific_variant_id(struct device *dev,
						       int ssid_vendor,
						       int ssid_device);
struct dentry *cs_amp_create_debugfs(struct device *dev);

static inline u64 cs_amp_cal_target_u64(const struct cirrus_amp_cal_data *data)
+18 −0
Original line number Diff line number Diff line
@@ -786,9 +786,14 @@ config SND_SOC_CROS_EC_CODEC
config SND_SOC_CS_AMP_LIB
	tristate

config SND_SOC_CS_AMP_LIB_TEST_HOOKS
	bool
	depends on SND_SOC_CS_AMP_LIB

config SND_SOC_CS_AMP_LIB_TEST
	tristate "KUnit test for Cirrus Logic cs-amp-lib" if !KUNIT_ALL_TESTS
	depends on SND_SOC_CS_AMP_LIB && KUNIT
	select SND_SOC_CS_AMP_LIB_TEST_HOOKS
	default KUNIT_ALL_TESTS
	help
	  This builds KUnit tests for the Cirrus Logic common
@@ -928,6 +933,19 @@ config SND_SOC_CS35L56_CAL_SET_CTRL
	  On most platforms this is not needed.

	  If unsure select "N".

config SND_SOC_CS35L56_TEST
	tristate "KUnit test for Cirrus Logic cs35l56 driver" if !KUNIT_ALL_TESTS
	depends on SND_SOC_CS35L56 && KUNIT
	default KUNIT_ALL_TESTS
	select SND_SOC_CS_AMP_LIB_TEST_HOOKS
	help
	  This builds KUnit tests for the Cirrus Logic cs35l56
	  codec driver.
	  For more information on KUnit and unit tests in general,
	  please refer to the KUnit documentation in
	  Documentation/dev-tools/kunit/.
	  If in doubt, say "N".
endmenu

config SND_SOC_CS40L50
+2 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ snd-soc-cs35l56-shared-y := cs35l56-shared.o
snd-soc-cs35l56-i2c-y := cs35l56-i2c.o
snd-soc-cs35l56-spi-y := cs35l56-spi.o
snd-soc-cs35l56-sdw-y := cs35l56-sdw.o
snd-soc-cs35l56-test-y := cs35l56-test.o
snd-soc-cs40l50-y := cs40l50-codec.o
snd-soc-cs42l42-y := cs42l42.o
snd-soc-cs42l42-i2c-y := cs42l42-i2c.o
@@ -516,6 +517,7 @@ obj-$(CONFIG_SND_SOC_CS35L56_SHARED) += snd-soc-cs35l56-shared.o
obj-$(CONFIG_SND_SOC_CS35L56_I2C)	+= snd-soc-cs35l56-i2c.o
obj-$(CONFIG_SND_SOC_CS35L56_SPI)	+= snd-soc-cs35l56-spi.o
obj-$(CONFIG_SND_SOC_CS35L56_SDW)	+= snd-soc-cs35l56-sdw.o
obj-$(CONFIG_SND_SOC_CS35L56_TEST)	+= snd-soc-cs35l56-test.o
obj-$(CONFIG_SND_SOC_CS40L50)		+= snd-soc-cs40l50.o
obj-$(CONFIG_SND_SOC_CS42L42_CORE)	+= snd-soc-cs42l42.o
obj-$(CONFIG_SND_SOC_CS42L42)	+= snd-soc-cs42l42-i2c.o
+169 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/overflow.h>
#include <linux/pci_ids.h>
#include <linux/platform_device.h>
#include <linux/random.h>
#include <sound/cs-amp-lib.h>
@@ -56,6 +57,8 @@ struct cs_amp_lib_test_ctl_write_entry {
struct cs_amp_lib_test_param {
	int num_amps;
	int amp_index;
	char *vendor_sysid;
	char *expected_sysid;
};

static struct cirrus_amp_efi_data *cs_amp_lib_test_cal_blob_dup(struct kunit *test)
@@ -2305,6 +2308,98 @@ static void cs_amp_lib_test_spkid_hp_31(struct kunit *test)
	KUNIT_EXPECT_EQ(test, 1, cs_amp_get_vendor_spkid(dev));
}

static efi_status_t cs_amp_lib_test_get_efi_vendor_sysid(efi_char16_t *name,
							 efi_guid_t *guid,
							 u32 *returned_attr,
							 unsigned long *size,
							 void *buf)
{
	struct kunit *test = kunit_get_current_test();
	const struct cs_amp_lib_test_param *param = test->param_value;
	unsigned int len;

	KUNIT_ASSERT_NOT_NULL(test, param->vendor_sysid);
	len = strlen(param->vendor_sysid);

	if (*size < len) {
		*size = len;
		return EFI_BUFFER_TOO_SMALL;
	}

	KUNIT_ASSERT_NOT_NULL(test, buf);
	memcpy(buf, param->vendor_sysid, len);

	return EFI_SUCCESS;
}

/* Fetch SSIDExV2 string from UEFI */
static void cs_amp_lib_test_ssidexv2_fetch(struct kunit *test)
{
	const struct cs_amp_lib_test_param *param = test->param_value;
	struct cs_amp_lib_test_priv *priv = test->priv;
	struct device *dev = &priv->amp_dev->dev;
	const char *got;

	kunit_activate_static_stub(test,
				   cs_amp_test_hooks->get_efi_variable,
				   cs_amp_lib_test_get_efi_vendor_sysid);

	got = cs_amp_devm_get_vendor_specific_variant_id(dev, PCI_VENDOR_ID_DELL, 0xabcd);
	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, got);
	KUNIT_EXPECT_STREQ(test, got, param->expected_sysid);
}

/* Invalid SSIDExV2 string should be ignored */
static void cs_amp_lib_test_ssidexv2_fetch_invalid(struct kunit *test)
{
	struct cs_amp_lib_test_priv *priv = test->priv;
	struct device *dev = &priv->amp_dev->dev;
	const char *got;

	kunit_activate_static_stub(test,
				   cs_amp_test_hooks->get_efi_variable,
				   cs_amp_lib_test_get_efi_vendor_sysid);

	got = cs_amp_devm_get_vendor_specific_variant_id(dev, PCI_VENDOR_ID_DELL, 0xabcd);
	KUNIT_EXPECT_NOT_NULL(test, got);
	KUNIT_EXPECT_EQ(test, PTR_ERR_OR_ZERO(got), -ENOENT);
}

static void cs_amp_lib_test_ssidexv2_not_dell(struct kunit *test)
{
	struct cs_amp_lib_test_priv *priv = test->priv;
	struct device *dev = &priv->amp_dev->dev;
	const char *got;

	kunit_activate_static_stub(test,
				   cs_amp_test_hooks->get_efi_variable,
				   cs_amp_lib_test_get_efi_vendor_sysid);

	/* Not returned if SSID vendor is not Dell */
	got = cs_amp_devm_get_vendor_specific_variant_id(dev, PCI_VENDOR_ID_CIRRUS, 0xabcd);
	KUNIT_EXPECT_NOT_NULL(test, got);
	KUNIT_EXPECT_EQ(test, PTR_ERR_OR_ZERO(got), -ENOENT);
}

static void cs_amp_lib_test_vendor_variant_id_not_found(struct kunit *test)
{
	struct cs_amp_lib_test_priv *priv = test->priv;
	struct device *dev = &priv->amp_dev->dev;
	const char *got;

	kunit_activate_static_stub(test,
				   cs_amp_test_hooks->get_efi_variable,
				   cs_amp_lib_test_get_efi_variable_none);

	got = cs_amp_devm_get_vendor_specific_variant_id(dev, PCI_VENDOR_ID_DELL, 0xabcd);
	KUNIT_EXPECT_NOT_NULL(test, got);
	KUNIT_EXPECT_EQ(test, PTR_ERR_OR_ZERO(got), -ENOENT);

	got = cs_amp_devm_get_vendor_specific_variant_id(dev, -1, -1);
	KUNIT_EXPECT_NOT_NULL(test, got);
	KUNIT_EXPECT_EQ(test, PTR_ERR_OR_ZERO(got), -ENOENT);
}

static int cs_amp_lib_test_case_init(struct kunit *test)
{
	struct cs_amp_lib_test_priv *priv;
@@ -2375,6 +2470,71 @@ static void cs_amp_lib_test_get_cal_param_desc(const struct cs_amp_lib_test_para
KUNIT_ARRAY_PARAM(cs_amp_lib_test_get_cal, cs_amp_lib_test_get_cal_param_cases,
		  cs_amp_lib_test_get_cal_param_desc);

static const struct cs_amp_lib_test_param cs_amp_lib_test_ssidexv2_param_cases[] = {
	{ .vendor_sysid = "abcd_00",		.expected_sysid = "00" },
	{ .vendor_sysid = "abcd_01",		.expected_sysid = "01" },
	{ .vendor_sysid = "abcd_XY",		.expected_sysid = "XY" },

	{ .vendor_sysid = "1028abcd_00",	.expected_sysid = "00" },
	{ .vendor_sysid = "1028abcd_01",	.expected_sysid = "01" },
	{ .vendor_sysid = "1028abcd_XY",	.expected_sysid = "XY" },

	{ .vendor_sysid = "abcd_00_WF",		.expected_sysid = "00" },
	{ .vendor_sysid = "abcd_01_WF",		.expected_sysid = "01" },
	{ .vendor_sysid = "abcd_XY_WF",		.expected_sysid = "XY" },

	{ .vendor_sysid = "1028abcd_00_WF",	.expected_sysid = "00" },
	{ .vendor_sysid = "1028abcd_01_WF",	.expected_sysid = "01" },
	{ .vendor_sysid = "1028abcd_XY_WF",	.expected_sysid = "XY" },

	{ .vendor_sysid = "abcd_00_AA_BB",	.expected_sysid = "00" },
	{ .vendor_sysid = "abcd_01_AA_BB",	.expected_sysid = "01" },
	{ .vendor_sysid = "abcd_XY_AA_BB",	.expected_sysid = "XY" },

	{ .vendor_sysid = "1028abcd_00_AA_BB",	.expected_sysid = "00" },
	{ .vendor_sysid = "1028abcd_01_AA_BB",	.expected_sysid = "01" },
	{ .vendor_sysid = "1028abcd_XY_A_BB",	.expected_sysid = "XY" },
};

static void cs_amp_lib_test_ssidexv2_param_desc(const struct cs_amp_lib_test_param *param,
						char *desc)
{
	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "vendor_sysid:'%s' expected_sysid:'%s'",
		 param->vendor_sysid, param->expected_sysid);
}

KUNIT_ARRAY_PARAM(cs_amp_lib_test_ssidexv2, cs_amp_lib_test_ssidexv2_param_cases,
		  cs_amp_lib_test_ssidexv2_param_desc);

static const struct cs_amp_lib_test_param cs_amp_lib_test_ssidexv2_invalid_param_cases[] = {
	{ .vendor_sysid = "abcd" },
	{ .vendor_sysid = "abcd_0" },
	{ .vendor_sysid = "abcd_1" },
	{ .vendor_sysid = "abcd_0_1" },
	{ .vendor_sysid = "abcd_1_1" },
	{ .vendor_sysid = "abcd_1_X" },
	{ .vendor_sysid = "abcd_1_X" },
	{ .vendor_sysid = "abcd_000" },
	{ .vendor_sysid = "abcd_010" },
	{ .vendor_sysid = "abcd_000_01" },
	{ .vendor_sysid = "abcd_000_01" },

	{ .vendor_sysid = "1234abcd" },
	{ .vendor_sysid = "1234abcd_0" },
	{ .vendor_sysid = "1234abcd_1" },
	{ .vendor_sysid = "1234abcd_0_1" },
	{ .vendor_sysid = "1234abcd_1_1" },
	{ .vendor_sysid = "1234abcd_1_X" },
	{ .vendor_sysid = "1234abcd_1_X" },
	{ .vendor_sysid = "1234abcd_000" },
	{ .vendor_sysid = "1234abcd_010" },
	{ .vendor_sysid = "1234abcd_000_01" },
	{ .vendor_sysid = "1234abcd_000_01" },
};

KUNIT_ARRAY_PARAM(cs_amp_lib_test_ssidexv2_invalid, cs_amp_lib_test_ssidexv2_invalid_param_cases,
		  cs_amp_lib_test_ssidexv2_param_desc);

static struct kunit_case cs_amp_lib_test_cases[] = {
	/* Tests for getting calibration data from EFI */
	KUNIT_CASE(cs_amp_lib_test_cal_data_too_short_test),
@@ -2434,6 +2594,15 @@ static struct kunit_case cs_amp_lib_test_cases[] = {
	KUNIT_CASE(cs_amp_lib_test_spkid_hp_30),
	KUNIT_CASE(cs_amp_lib_test_spkid_hp_31),

	/* Test cases for SSIDExV2 */
	KUNIT_CASE_PARAM(cs_amp_lib_test_ssidexv2_fetch,
			 cs_amp_lib_test_ssidexv2_gen_params),
	KUNIT_CASE_PARAM(cs_amp_lib_test_ssidexv2_fetch_invalid,
			 cs_amp_lib_test_ssidexv2_invalid_gen_params),
	KUNIT_CASE_PARAM(cs_amp_lib_test_ssidexv2_not_dell,
			 cs_amp_lib_test_ssidexv2_gen_params),
	KUNIT_CASE(cs_amp_lib_test_vendor_variant_id_not_found),

	{ } /* terminator */
};

+121 −10
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/overflow.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/timekeeping.h>
#include <linux/types.h>
@@ -36,6 +37,10 @@
#define HP_CALIBRATION_EFI_GUID \
	EFI_GUID(0x53559579, 0x8753, 0x4f5c, 0x91, 0x30, 0xe8, 0x2a, 0xcf, 0xb8, 0xd8, 0x93)

#define DELL_SSIDEXV2_EFI_NAME L"SSIDexV2Data"
#define DELL_SSIDEXV2_EFI_GUID \
	EFI_GUID(0x6a5f35df, 0x1432, 0x4656, 0x85, 0x97, 0x31, 0x04, 0xd5, 0xbf, 0x3a, 0xb0)

static const struct cs_amp_lib_cal_efivar {
	efi_char16_t *name;
	efi_guid_t *guid;
@@ -206,7 +211,7 @@ int cs_amp_write_cal_coeffs(struct cs_dsp *dsp,
			    const struct cirrus_amp_cal_controls *controls,
			    const struct cirrus_amp_cal_data *data)
{
	if (IS_REACHABLE(CONFIG_FW_CS_DSP) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST))
	if (IS_REACHABLE(CONFIG_FW_CS_DSP) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS))
		return _cs_amp_write_cal_coeffs(dsp, controls, data);
	else
		return -ENODEV;
@@ -225,7 +230,7 @@ int cs_amp_read_cal_coeffs(struct cs_dsp *dsp,
			   const struct cirrus_amp_cal_controls *controls,
			   struct cirrus_amp_cal_data *data)
{
	if (IS_REACHABLE(CONFIG_FW_CS_DSP) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST))
	if (IS_REACHABLE(CONFIG_FW_CS_DSP) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS))
		return _cs_amp_read_cal_coeffs(dsp, controls, data);
	else
		return -ENODEV;
@@ -244,10 +249,7 @@ int cs_amp_write_ambient_temp(struct cs_dsp *dsp,
			      const struct cirrus_amp_cal_controls *controls,
			      u32 temp)
{
	if (IS_REACHABLE(CONFIG_FW_CS_DSP) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST))
	return cs_amp_write_cal_coeff(dsp, controls, controls->ambient, temp);
	else
		return -ENODEV;
}
EXPORT_SYMBOL_NS_GPL(cs_amp_write_ambient_temp, "SND_SOC_CS_AMP_LIB");

@@ -304,6 +306,29 @@ static int cs_amp_convert_efi_status(efi_status_t status)
	}
}

static void *cs_amp_alloc_get_efi_variable(efi_char16_t *name,
					   efi_guid_t *guid,
					   u32 *returned_attr)
{
	efi_status_t status;
	unsigned long size = 0;

	status = cs_amp_get_efi_variable(name, guid, NULL, &size, NULL);
	if (status != EFI_BUFFER_TOO_SMALL)
		return ERR_PTR(cs_amp_convert_efi_status(status));

	/* Over-alloc to ensure strings are always NUL-terminated */
	void *buf __free(kfree) = kzalloc(size + 1, GFP_KERNEL);
	if (!buf)
		return ERR_PTR(-ENOMEM);

	status = cs_amp_get_efi_variable(name, guid, returned_attr, &size, buf);
	if (status != EFI_SUCCESS)
		return ERR_PTR(cs_amp_convert_efi_status(status));

	return_ptr(buf);
}

static struct cirrus_amp_efi_data *cs_amp_get_cal_efi_buffer(struct device *dev,
							     efi_char16_t **name,
							     efi_guid_t **guid,
@@ -583,7 +608,7 @@ static int _cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, i
int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_index,
				    struct cirrus_amp_cal_data *out_data)
{
	if (IS_ENABLED(CONFIG_EFI) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST))
	if (IS_ENABLED(CONFIG_EFI) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS))
		return _cs_amp_get_efi_calibration_data(dev, target_uid, amp_index, out_data);
	else
		return -ENOENT;
@@ -619,7 +644,7 @@ EXPORT_SYMBOL_NS_GPL(cs_amp_get_efi_calibration_data, "SND_SOC_CS_AMP_LIB");
int cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, int num_amps,
				    const struct cirrus_amp_cal_data *in_data)
{
	if (IS_ENABLED(CONFIG_EFI) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST)) {
	if (IS_ENABLED(CONFIG_EFI) || IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS)) {
		scoped_guard(mutex, &cs_amp_efi_cal_write_lock) {
			return _cs_amp_set_efi_calibration_data(dev, amp_index,
								num_amps, in_data);
@@ -692,7 +717,7 @@ int cs_amp_get_vendor_spkid(struct device *dev)
	int i, ret;

	if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE) &&
	    !IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST))
	    !IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS))
		return -ENOENT;

	for (i = 0; i < ARRAY_SIZE(cs_amp_spkid_byte_types); i++) {
@@ -705,6 +730,92 @@ int cs_amp_get_vendor_spkid(struct device *dev)
}
EXPORT_SYMBOL_NS_GPL(cs_amp_get_vendor_spkid, "SND_SOC_CS_AMP_LIB");

static const char *cs_amp_devm_get_dell_ssidex(struct device *dev,
					       int ssid_vendor, int ssid_device)
{
	unsigned int hex_prefix;
	char audio_id[4];
	char delim;
	char *p;
	int ret;

	if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE) &&
	    !IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS))
		return ERR_PTR(-ENOENT);

	char *ssidex_buf __free(kfree) = cs_amp_alloc_get_efi_variable(DELL_SSIDEXV2_EFI_NAME,
								       &DELL_SSIDEXV2_EFI_GUID,
								       NULL);
	ret = PTR_ERR_OR_ZERO(ssidex_buf);
	if (ret == -ENOENT)
		return ERR_PTR(-ENOENT);
	else if (ret < 0)
		return ssidex_buf;

	/*
	 * SSIDExV2 string is a series of underscore delimited fields.
	 * First field is all or part of the SSID. Second field should be
	 * a 2-character audio hardware id, followed by other identifiers.
	 * Older models did not have the 2-character audio id, so reject
	 * the string if the second field is not 2 characters.
	 */
	ret = sscanf(ssidex_buf, "%8x_%2s%c", &hex_prefix, audio_id, &delim);
	if (ret < 2)
		return ERR_PTR(-ENOENT);

	if ((ret == 3) && (delim != '_'))
		return ERR_PTR(-ENOENT);

	if (strlen(audio_id) != 2)
		return ERR_PTR(-ENOENT);

	p = devm_kstrdup(dev, audio_id, GFP_KERNEL);
	if (!p)
		return ERR_PTR(-ENOMEM);

	return p;
}

/**
 * cs_amp_devm_get_vendor_specific_variant_id - get variant ID string
 * @dev:	 pointer to struct device
 * @ssid_vendor: PCI Subsystem Vendor (-1 if unknown)
 * @ssid_device: PCI Subsystem Device (-1 if unknown)
 *
 * Known vendor-specific hardware identifiers are checked and if one is
 * found its content is returned as a NUL-terminated string. The returned
 * string is devm-managed.
 *
 * The returned string is not guaranteed to be globally unique.
 * Generally it should be combined with some other qualifier, such as
 * PCI SSID, to create a globally unique ID.
 *
 * If the caller has a PCI SSID it should pass it in @ssid_vendor and
 * @ssid_device. If the vendor-spefic ID contains this SSID it will be
 * stripped from the returned string to prevent duplication.
 *
 * If the caller does not have a PCI SSID, pass -1 for @ssid_vendor and
 * @ssid_device.
 *
 * Return:
 * * a pointer to a devm-managed string
 * * ERR_PTR(-ENOENT) if no vendor-specific qualifier
 * * ERR_PTR error value
 */
const char *cs_amp_devm_get_vendor_specific_variant_id(struct device *dev,
						       int ssid_vendor,
						       int ssid_device)
{
	KUNIT_STATIC_STUB_REDIRECT(cs_amp_devm_get_vendor_specific_variant_id,
				   dev, ssid_vendor, ssid_device);

	if ((ssid_vendor == PCI_VENDOR_ID_DELL) || (ssid_vendor < 0))
		return cs_amp_devm_get_dell_ssidex(dev, ssid_vendor, ssid_device);

	return ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL_NS_GPL(cs_amp_devm_get_vendor_specific_variant_id, "SND_SOC_CS_AMP_LIB");

/**
 * cs_amp_create_debugfs - create a debugfs directory for a device
 *
@@ -738,7 +849,7 @@ static const struct cs_amp_test_hooks cs_amp_test_hook_ptrs = {
};

const struct cs_amp_test_hooks * const cs_amp_test_hooks =
	PTR_IF(IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST), &cs_amp_test_hook_ptrs);
	PTR_IF(IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS), &cs_amp_test_hook_ptrs);
EXPORT_SYMBOL_NS_GPL(cs_amp_test_hooks, "SND_SOC_CS_AMP_LIB");

MODULE_DESCRIPTION("Cirrus Logic amplifier library");
Loading