Skip to content

Commit be9d8d9

Browse files
committed
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.
2 parents 7f42828 + d0ab899 commit be9d8d9

8 files changed

Lines changed: 741 additions & 25 deletions

File tree

include/sound/cs-amp-lib.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_
5858
int cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, int num_amps,
5959
const struct cirrus_amp_cal_data *in_data);
6060
int cs_amp_get_vendor_spkid(struct device *dev);
61+
const char *cs_amp_devm_get_vendor_specific_variant_id(struct device *dev,
62+
int ssid_vendor,
63+
int ssid_device);
6164
struct dentry *cs_amp_create_debugfs(struct device *dev);
6265

6366
static inline u64 cs_amp_cal_target_u64(const struct cirrus_amp_cal_data *data)

sound/soc/codecs/Kconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,14 @@ config SND_SOC_CROS_EC_CODEC
786786
config SND_SOC_CS_AMP_LIB
787787
tristate
788788

789+
config SND_SOC_CS_AMP_LIB_TEST_HOOKS
790+
bool
791+
depends on SND_SOC_CS_AMP_LIB
792+
789793
config SND_SOC_CS_AMP_LIB_TEST
790794
tristate "KUnit test for Cirrus Logic cs-amp-lib" if !KUNIT_ALL_TESTS
791795
depends on SND_SOC_CS_AMP_LIB && KUNIT
796+
select SND_SOC_CS_AMP_LIB_TEST_HOOKS
792797
default KUNIT_ALL_TESTS
793798
help
794799
This builds KUnit tests for the Cirrus Logic common
@@ -928,6 +933,19 @@ config SND_SOC_CS35L56_CAL_SET_CTRL
928933
On most platforms this is not needed.
929934

930935
If unsure select "N".
936+
937+
config SND_SOC_CS35L56_TEST
938+
tristate "KUnit test for Cirrus Logic cs35l56 driver" if !KUNIT_ALL_TESTS
939+
depends on SND_SOC_CS35L56 && KUNIT
940+
default KUNIT_ALL_TESTS
941+
select SND_SOC_CS_AMP_LIB_TEST_HOOKS
942+
help
943+
This builds KUnit tests for the Cirrus Logic cs35l56
944+
codec driver.
945+
For more information on KUnit and unit tests in general,
946+
please refer to the KUnit documentation in
947+
Documentation/dev-tools/kunit/.
948+
If in doubt, say "N".
931949
endmenu
932950

933951
config SND_SOC_CS40L50

sound/soc/codecs/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ snd-soc-cs35l56-shared-y := cs35l56-shared.o
8181
snd-soc-cs35l56-i2c-y := cs35l56-i2c.o
8282
snd-soc-cs35l56-spi-y := cs35l56-spi.o
8383
snd-soc-cs35l56-sdw-y := cs35l56-sdw.o
84+
snd-soc-cs35l56-test-y := cs35l56-test.o
8485
snd-soc-cs40l50-y := cs40l50-codec.o
8586
snd-soc-cs42l42-y := cs42l42.o
8687
snd-soc-cs42l42-i2c-y := cs42l42-i2c.o
@@ -516,6 +517,7 @@ obj-$(CONFIG_SND_SOC_CS35L56_SHARED) += snd-soc-cs35l56-shared.o
516517
obj-$(CONFIG_SND_SOC_CS35L56_I2C) += snd-soc-cs35l56-i2c.o
517518
obj-$(CONFIG_SND_SOC_CS35L56_SPI) += snd-soc-cs35l56-spi.o
518519
obj-$(CONFIG_SND_SOC_CS35L56_SDW) += snd-soc-cs35l56-sdw.o
520+
obj-$(CONFIG_SND_SOC_CS35L56_TEST) += snd-soc-cs35l56-test.o
519521
obj-$(CONFIG_SND_SOC_CS40L50) += snd-soc-cs40l50.o
520522
obj-$(CONFIG_SND_SOC_CS42L42_CORE) += snd-soc-cs42l42.o
521523
obj-$(CONFIG_SND_SOC_CS42L42) += snd-soc-cs42l42-i2c.o

sound/soc/codecs/cs-amp-lib-test.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/list.h>
1717
#include <linux/module.h>
1818
#include <linux/overflow.h>
19+
#include <linux/pci_ids.h>
1920
#include <linux/platform_device.h>
2021
#include <linux/random.h>
2122
#include <sound/cs-amp-lib.h>
@@ -56,6 +57,8 @@ struct cs_amp_lib_test_ctl_write_entry {
5657
struct cs_amp_lib_test_param {
5758
int num_amps;
5859
int amp_index;
60+
char *vendor_sysid;
61+
char *expected_sysid;
5962
};
6063

6164
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)
23052308
KUNIT_EXPECT_EQ(test, 1, cs_amp_get_vendor_spkid(dev));
23062309
}
23072310

2311+
static efi_status_t cs_amp_lib_test_get_efi_vendor_sysid(efi_char16_t *name,
2312+
efi_guid_t *guid,
2313+
u32 *returned_attr,
2314+
unsigned long *size,
2315+
void *buf)
2316+
{
2317+
struct kunit *test = kunit_get_current_test();
2318+
const struct cs_amp_lib_test_param *param = test->param_value;
2319+
unsigned int len;
2320+
2321+
KUNIT_ASSERT_NOT_NULL(test, param->vendor_sysid);
2322+
len = strlen(param->vendor_sysid);
2323+
2324+
if (*size < len) {
2325+
*size = len;
2326+
return EFI_BUFFER_TOO_SMALL;
2327+
}
2328+
2329+
KUNIT_ASSERT_NOT_NULL(test, buf);
2330+
memcpy(buf, param->vendor_sysid, len);
2331+
2332+
return EFI_SUCCESS;
2333+
}
2334+
2335+
/* Fetch SSIDExV2 string from UEFI */
2336+
static void cs_amp_lib_test_ssidexv2_fetch(struct kunit *test)
2337+
{
2338+
const struct cs_amp_lib_test_param *param = test->param_value;
2339+
struct cs_amp_lib_test_priv *priv = test->priv;
2340+
struct device *dev = &priv->amp_dev->dev;
2341+
const char *got;
2342+
2343+
kunit_activate_static_stub(test,
2344+
cs_amp_test_hooks->get_efi_variable,
2345+
cs_amp_lib_test_get_efi_vendor_sysid);
2346+
2347+
got = cs_amp_devm_get_vendor_specific_variant_id(dev, PCI_VENDOR_ID_DELL, 0xabcd);
2348+
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, got);
2349+
KUNIT_EXPECT_STREQ(test, got, param->expected_sysid);
2350+
}
2351+
2352+
/* Invalid SSIDExV2 string should be ignored */
2353+
static void cs_amp_lib_test_ssidexv2_fetch_invalid(struct kunit *test)
2354+
{
2355+
struct cs_amp_lib_test_priv *priv = test->priv;
2356+
struct device *dev = &priv->amp_dev->dev;
2357+
const char *got;
2358+
2359+
kunit_activate_static_stub(test,
2360+
cs_amp_test_hooks->get_efi_variable,
2361+
cs_amp_lib_test_get_efi_vendor_sysid);
2362+
2363+
got = cs_amp_devm_get_vendor_specific_variant_id(dev, PCI_VENDOR_ID_DELL, 0xabcd);
2364+
KUNIT_EXPECT_NOT_NULL(test, got);
2365+
KUNIT_EXPECT_EQ(test, PTR_ERR_OR_ZERO(got), -ENOENT);
2366+
}
2367+
2368+
static void cs_amp_lib_test_ssidexv2_not_dell(struct kunit *test)
2369+
{
2370+
struct cs_amp_lib_test_priv *priv = test->priv;
2371+
struct device *dev = &priv->amp_dev->dev;
2372+
const char *got;
2373+
2374+
kunit_activate_static_stub(test,
2375+
cs_amp_test_hooks->get_efi_variable,
2376+
cs_amp_lib_test_get_efi_vendor_sysid);
2377+
2378+
/* Not returned if SSID vendor is not Dell */
2379+
got = cs_amp_devm_get_vendor_specific_variant_id(dev, PCI_VENDOR_ID_CIRRUS, 0xabcd);
2380+
KUNIT_EXPECT_NOT_NULL(test, got);
2381+
KUNIT_EXPECT_EQ(test, PTR_ERR_OR_ZERO(got), -ENOENT);
2382+
}
2383+
2384+
static void cs_amp_lib_test_vendor_variant_id_not_found(struct kunit *test)
2385+
{
2386+
struct cs_amp_lib_test_priv *priv = test->priv;
2387+
struct device *dev = &priv->amp_dev->dev;
2388+
const char *got;
2389+
2390+
kunit_activate_static_stub(test,
2391+
cs_amp_test_hooks->get_efi_variable,
2392+
cs_amp_lib_test_get_efi_variable_none);
2393+
2394+
got = cs_amp_devm_get_vendor_specific_variant_id(dev, PCI_VENDOR_ID_DELL, 0xabcd);
2395+
KUNIT_EXPECT_NOT_NULL(test, got);
2396+
KUNIT_EXPECT_EQ(test, PTR_ERR_OR_ZERO(got), -ENOENT);
2397+
2398+
got = cs_amp_devm_get_vendor_specific_variant_id(dev, -1, -1);
2399+
KUNIT_EXPECT_NOT_NULL(test, got);
2400+
KUNIT_EXPECT_EQ(test, PTR_ERR_OR_ZERO(got), -ENOENT);
2401+
}
2402+
23082403
static int cs_amp_lib_test_case_init(struct kunit *test)
23092404
{
23102405
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
23752470
KUNIT_ARRAY_PARAM(cs_amp_lib_test_get_cal, cs_amp_lib_test_get_cal_param_cases,
23762471
cs_amp_lib_test_get_cal_param_desc);
23772472

2473+
static const struct cs_amp_lib_test_param cs_amp_lib_test_ssidexv2_param_cases[] = {
2474+
{ .vendor_sysid = "abcd_00", .expected_sysid = "00" },
2475+
{ .vendor_sysid = "abcd_01", .expected_sysid = "01" },
2476+
{ .vendor_sysid = "abcd_XY", .expected_sysid = "XY" },
2477+
2478+
{ .vendor_sysid = "1028abcd_00", .expected_sysid = "00" },
2479+
{ .vendor_sysid = "1028abcd_01", .expected_sysid = "01" },
2480+
{ .vendor_sysid = "1028abcd_XY", .expected_sysid = "XY" },
2481+
2482+
{ .vendor_sysid = "abcd_00_WF", .expected_sysid = "00" },
2483+
{ .vendor_sysid = "abcd_01_WF", .expected_sysid = "01" },
2484+
{ .vendor_sysid = "abcd_XY_WF", .expected_sysid = "XY" },
2485+
2486+
{ .vendor_sysid = "1028abcd_00_WF", .expected_sysid = "00" },
2487+
{ .vendor_sysid = "1028abcd_01_WF", .expected_sysid = "01" },
2488+
{ .vendor_sysid = "1028abcd_XY_WF", .expected_sysid = "XY" },
2489+
2490+
{ .vendor_sysid = "abcd_00_AA_BB", .expected_sysid = "00" },
2491+
{ .vendor_sysid = "abcd_01_AA_BB", .expected_sysid = "01" },
2492+
{ .vendor_sysid = "abcd_XY_AA_BB", .expected_sysid = "XY" },
2493+
2494+
{ .vendor_sysid = "1028abcd_00_AA_BB", .expected_sysid = "00" },
2495+
{ .vendor_sysid = "1028abcd_01_AA_BB", .expected_sysid = "01" },
2496+
{ .vendor_sysid = "1028abcd_XY_A_BB", .expected_sysid = "XY" },
2497+
};
2498+
2499+
static void cs_amp_lib_test_ssidexv2_param_desc(const struct cs_amp_lib_test_param *param,
2500+
char *desc)
2501+
{
2502+
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "vendor_sysid:'%s' expected_sysid:'%s'",
2503+
param->vendor_sysid, param->expected_sysid);
2504+
}
2505+
2506+
KUNIT_ARRAY_PARAM(cs_amp_lib_test_ssidexv2, cs_amp_lib_test_ssidexv2_param_cases,
2507+
cs_amp_lib_test_ssidexv2_param_desc);
2508+
2509+
static const struct cs_amp_lib_test_param cs_amp_lib_test_ssidexv2_invalid_param_cases[] = {
2510+
{ .vendor_sysid = "abcd" },
2511+
{ .vendor_sysid = "abcd_0" },
2512+
{ .vendor_sysid = "abcd_1" },
2513+
{ .vendor_sysid = "abcd_0_1" },
2514+
{ .vendor_sysid = "abcd_1_1" },
2515+
{ .vendor_sysid = "abcd_1_X" },
2516+
{ .vendor_sysid = "abcd_1_X" },
2517+
{ .vendor_sysid = "abcd_000" },
2518+
{ .vendor_sysid = "abcd_010" },
2519+
{ .vendor_sysid = "abcd_000_01" },
2520+
{ .vendor_sysid = "abcd_000_01" },
2521+
2522+
{ .vendor_sysid = "1234abcd" },
2523+
{ .vendor_sysid = "1234abcd_0" },
2524+
{ .vendor_sysid = "1234abcd_1" },
2525+
{ .vendor_sysid = "1234abcd_0_1" },
2526+
{ .vendor_sysid = "1234abcd_1_1" },
2527+
{ .vendor_sysid = "1234abcd_1_X" },
2528+
{ .vendor_sysid = "1234abcd_1_X" },
2529+
{ .vendor_sysid = "1234abcd_000" },
2530+
{ .vendor_sysid = "1234abcd_010" },
2531+
{ .vendor_sysid = "1234abcd_000_01" },
2532+
{ .vendor_sysid = "1234abcd_000_01" },
2533+
};
2534+
2535+
KUNIT_ARRAY_PARAM(cs_amp_lib_test_ssidexv2_invalid, cs_amp_lib_test_ssidexv2_invalid_param_cases,
2536+
cs_amp_lib_test_ssidexv2_param_desc);
2537+
23782538
static struct kunit_case cs_amp_lib_test_cases[] = {
23792539
/* Tests for getting calibration data from EFI */
23802540
KUNIT_CASE(cs_amp_lib_test_cal_data_too_short_test),
@@ -2434,6 +2594,15 @@ static struct kunit_case cs_amp_lib_test_cases[] = {
24342594
KUNIT_CASE(cs_amp_lib_test_spkid_hp_30),
24352595
KUNIT_CASE(cs_amp_lib_test_spkid_hp_31),
24362596

2597+
/* Test cases for SSIDExV2 */
2598+
KUNIT_CASE_PARAM(cs_amp_lib_test_ssidexv2_fetch,
2599+
cs_amp_lib_test_ssidexv2_gen_params),
2600+
KUNIT_CASE_PARAM(cs_amp_lib_test_ssidexv2_fetch_invalid,
2601+
cs_amp_lib_test_ssidexv2_invalid_gen_params),
2602+
KUNIT_CASE_PARAM(cs_amp_lib_test_ssidexv2_not_dell,
2603+
cs_amp_lib_test_ssidexv2_gen_params),
2604+
KUNIT_CASE(cs_amp_lib_test_vendor_variant_id_not_found),
2605+
24372606
{ } /* terminator */
24382607
};
24392608

0 commit comments

Comments
 (0)