Skip to content

Commit 32bd60d

Browse files
committed
ASoC: cs35l56: Handle vendor-specific UEFI
Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>: This series adds handling for vendor-specific UEFI variables from Lenovo and HP. These vendors will switch to using their UEFI variables instead of the normal Cirrus Logic-defined mechanisms. The model of speaker fitted (Speaker ID) is normally signaled by a GPIO, and the driver is given access to this GPIO. Lenovo and HP will both stop giving the driver access to the GPIO and instead the BIOS will create a UEFI variable giving the value of the GPIO. HP will also start using their own UEFI variable to store amp calibration data. The content of the variable is the same as the Cirrus Logic variable, only the UEFI name and GUID are changed. Change in v2: Removed unused target_uid variable and code that set it in patch 6. Richard Fitzgerald (6): ASoC: cs-amp-lib: Rename defines for Cirrus Logic EFI ASoC: cs-amp-lib: Add handling for Lenovo and HP UEFI speaker ID ASoC: cs35l56: Check for vendor-specific speaker ID value ASoC: cs-amp-lib-test: Add tests for cs_amp_get_vendor_spkid() ASoC: cs-amp-lib: Add HP-specific EFI variable for calibration data ASoC: cs-amp-lib-test: Add test for getting cal data from HP EFI include/sound/cs-amp-lib.h | 1 + sound/soc/codecs/cs-amp-lib-test.c | 252 ++++++++++++++++++++++++++++- sound/soc/codecs/cs-amp-lib.c | 139 +++++++++++++++- sound/soc/codecs/cs35l56-shared.c | 12 +- 4 files changed, 395 insertions(+), 9 deletions(-) -- 2.39.5
2 parents c996429 + e5b4ad2 commit 32bd60d

4 files changed

Lines changed: 395 additions & 9 deletions

File tree

include/sound/cs-amp-lib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ int cs_amp_write_cal_coeffs(struct cs_dsp *dsp,
4949
const struct cirrus_amp_cal_data *data);
5050
int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_index,
5151
struct cirrus_amp_cal_data *out_data);
52+
int cs_amp_get_vendor_spkid(struct device *dev);
5253

5354
struct cs_amp_test_hooks {
5455
efi_status_t (*get_efi_variable)(efi_char16_t *name,

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

Lines changed: 250 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919
#include <linux/random.h>
2020
#include <sound/cs-amp-lib.h>
2121

22+
#define LENOVO_SPEAKER_ID_EFI_NAME L"SdwSpeaker"
23+
#define LENOVO_SPEAKER_ID_EFI_GUID \
24+
EFI_GUID(0x48df970e, 0xe27f, 0x460a, 0xb5, 0x86, 0x77, 0x19, 0x80, 0x1d, 0x92, 0x82)
25+
26+
#define HP_SPEAKER_ID_EFI_NAME L"HPSpeakerID"
27+
#define HP_SPEAKER_ID_EFI_GUID \
28+
EFI_GUID(0xc49593a4, 0xd099, 0x419b, 0xa2, 0xc3, 0x67, 0xe9, 0x80, 0xe6, 0x1d, 0x1e)
29+
2230
KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
2331
struct faux_device *)
2432

@@ -196,8 +204,40 @@ static efi_status_t cs_amp_lib_test_get_efi_variable(efi_char16_t *name,
196204
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, guid);
197205
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, size);
198206

199-
KUNIT_EXPECT_MEMEQ(test, name, expected_name, sizeof(expected_name));
200-
KUNIT_EXPECT_MEMEQ(test, guid, &expected_guid, sizeof(expected_guid));
207+
if (memcmp(name, expected_name, sizeof(expected_name)) ||
208+
efi_guidcmp(*guid, expected_guid))
209+
return -EFI_NOT_FOUND;
210+
211+
if (!buf) {
212+
*size = priv->cal_blob->size;
213+
return EFI_BUFFER_TOO_SMALL;
214+
}
215+
216+
KUNIT_ASSERT_GE_MSG(test, ksize(buf), priv->cal_blob->size, "Buffer to small");
217+
218+
memcpy(buf, priv->cal_blob, priv->cal_blob->size);
219+
220+
return EFI_SUCCESS;
221+
}
222+
223+
static efi_status_t cs_amp_lib_test_get_hp_cal_efi_variable(efi_char16_t *name,
224+
efi_guid_t *guid,
225+
unsigned long *size,
226+
void *buf)
227+
{
228+
static const efi_char16_t expected_name[] = L"SmartAmpCalibrationData";
229+
static const efi_guid_t expected_guid =
230+
EFI_GUID(0x53559579, 0x8753, 0x4f5c, 0x91, 0x30, 0xe8, 0x2a, 0xcf, 0xb8, 0xd8, 0x93);
231+
struct kunit *test = kunit_get_current_test();
232+
struct cs_amp_lib_test_priv *priv = test->priv;
233+
234+
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, name);
235+
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, guid);
236+
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, size);
237+
238+
if (memcmp(name, expected_name, sizeof(expected_name)) ||
239+
efi_guidcmp(*guid, expected_guid))
240+
return -EFI_NOT_FOUND;
201241

202242
if (!buf) {
203243
*size = priv->cal_blob->size;
@@ -211,6 +251,25 @@ static efi_status_t cs_amp_lib_test_get_efi_variable(efi_char16_t *name,
211251
return EFI_SUCCESS;
212252
}
213253

254+
/* Get cal data block from HP variable. */
255+
static void cs_amp_lib_test_get_hp_efi_cal(struct kunit *test)
256+
{
257+
struct cs_amp_lib_test_priv *priv = test->priv;
258+
struct cirrus_amp_cal_data result_data;
259+
int ret;
260+
261+
cs_amp_lib_test_init_dummy_cal_blob(test, 2);
262+
263+
kunit_activate_static_stub(test,
264+
cs_amp_test_hooks->get_efi_variable,
265+
cs_amp_lib_test_get_hp_cal_efi_variable);
266+
267+
ret = cs_amp_get_efi_calibration_data(&priv->amp_dev->dev, 0, 0, &result_data);
268+
KUNIT_EXPECT_EQ(test, ret, 0);
269+
270+
KUNIT_EXPECT_MEMEQ(test, &result_data, &priv->cal_blob->data[0], sizeof(result_data));
271+
}
272+
214273
/* Get cal data block for a given amp, matched by target UID. */
215274
static void cs_amp_lib_test_get_efi_cal_by_uid_test(struct kunit *test)
216275
{
@@ -642,6 +701,185 @@ static void cs_amp_lib_test_write_cal_data_test(struct kunit *test)
642701
KUNIT_EXPECT_EQ(test, entry->value, data.calStatus);
643702
}
644703

704+
static void cs_amp_lib_test_spkid_lenovo_not_present(struct kunit *test)
705+
{
706+
struct cs_amp_lib_test_priv *priv = test->priv;
707+
struct device *dev = &priv->amp_dev->dev;
708+
709+
kunit_activate_static_stub(test,
710+
cs_amp_test_hooks->get_efi_variable,
711+
cs_amp_lib_test_get_efi_variable_none);
712+
713+
KUNIT_EXPECT_EQ(test, -ENOENT, cs_amp_get_vendor_spkid(dev));
714+
}
715+
716+
static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_d0(efi_char16_t *name,
717+
efi_guid_t *guid,
718+
unsigned long *size,
719+
void *buf)
720+
{
721+
struct kunit *test = kunit_get_current_test();
722+
723+
if (efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID) ||
724+
memcmp(name, LENOVO_SPEAKER_ID_EFI_NAME, sizeof(LENOVO_SPEAKER_ID_EFI_NAME)))
725+
return EFI_NOT_FOUND;
726+
727+
KUNIT_ASSERT_EQ(test, *size, 1);
728+
*size = 1;
729+
*(u8 *)buf = 0xd0;
730+
731+
return EFI_SUCCESS;
732+
}
733+
734+
static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_d1(efi_char16_t *name,
735+
efi_guid_t *guid,
736+
unsigned long *size,
737+
void *buf)
738+
{
739+
struct kunit *test = kunit_get_current_test();
740+
741+
if (efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID) ||
742+
memcmp(name, LENOVO_SPEAKER_ID_EFI_NAME, sizeof(LENOVO_SPEAKER_ID_EFI_NAME)))
743+
return EFI_NOT_FOUND;
744+
745+
KUNIT_ASSERT_EQ(test, *size, 1);
746+
*size = 1;
747+
*(u8 *)buf = 0xd1;
748+
749+
return EFI_SUCCESS;
750+
}
751+
752+
static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_00(efi_char16_t *name,
753+
efi_guid_t *guid,
754+
unsigned long *size,
755+
void *buf)
756+
{
757+
struct kunit *test = kunit_get_current_test();
758+
759+
KUNIT_ASSERT_EQ(test, 0, efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID));
760+
KUNIT_ASSERT_EQ(test, *size, 1);
761+
*size = 1;
762+
*(u8 *)buf = 0;
763+
764+
return EFI_SUCCESS;
765+
}
766+
767+
static void cs_amp_lib_test_spkid_lenovo_d0(struct kunit *test)
768+
{
769+
struct cs_amp_lib_test_priv *priv = test->priv;
770+
struct device *dev = &priv->amp_dev->dev;
771+
772+
kunit_activate_static_stub(test,
773+
cs_amp_test_hooks->get_efi_variable,
774+
cs_amp_lib_test_get_efi_variable_lenovo_d0);
775+
776+
KUNIT_EXPECT_EQ(test, 0, cs_amp_get_vendor_spkid(dev));
777+
}
778+
779+
static void cs_amp_lib_test_spkid_lenovo_d1(struct kunit *test)
780+
{
781+
struct cs_amp_lib_test_priv *priv = test->priv;
782+
struct device *dev = &priv->amp_dev->dev;
783+
784+
kunit_activate_static_stub(test,
785+
cs_amp_test_hooks->get_efi_variable,
786+
cs_amp_lib_test_get_efi_variable_lenovo_d1);
787+
788+
KUNIT_EXPECT_EQ(test, 1, cs_amp_get_vendor_spkid(dev));
789+
}
790+
791+
static void cs_amp_lib_test_spkid_lenovo_illegal(struct kunit *test)
792+
{
793+
struct cs_amp_lib_test_priv *priv = test->priv;
794+
struct device *dev = &priv->amp_dev->dev;
795+
796+
kunit_activate_static_stub(test,
797+
cs_amp_test_hooks->get_efi_variable,
798+
cs_amp_lib_test_get_efi_variable_lenovo_00);
799+
800+
KUNIT_EXPECT_LT(test, cs_amp_get_vendor_spkid(dev), 0);
801+
}
802+
803+
static efi_status_t cs_amp_lib_test_get_efi_variable_buf_too_small(efi_char16_t *name,
804+
efi_guid_t *guid,
805+
unsigned long *size,
806+
void *buf)
807+
{
808+
return EFI_BUFFER_TOO_SMALL;
809+
}
810+
811+
static void cs_amp_lib_test_spkid_lenovo_oversize(struct kunit *test)
812+
{
813+
struct cs_amp_lib_test_priv *priv = test->priv;
814+
struct device *dev = &priv->amp_dev->dev;
815+
816+
kunit_activate_static_stub(test,
817+
cs_amp_test_hooks->get_efi_variable,
818+
cs_amp_lib_test_get_efi_variable_buf_too_small);
819+
820+
KUNIT_EXPECT_LT(test, cs_amp_get_vendor_spkid(dev), 0);
821+
}
822+
823+
static efi_status_t cs_amp_lib_test_get_efi_variable_hp_30(efi_char16_t *name,
824+
efi_guid_t *guid,
825+
unsigned long *size,
826+
void *buf)
827+
{
828+
struct kunit *test = kunit_get_current_test();
829+
830+
if (efi_guidcmp(*guid, HP_SPEAKER_ID_EFI_GUID) ||
831+
memcmp(name, HP_SPEAKER_ID_EFI_NAME, sizeof(HP_SPEAKER_ID_EFI_NAME)))
832+
return EFI_NOT_FOUND;
833+
834+
KUNIT_ASSERT_EQ(test, *size, 1);
835+
*size = 1;
836+
*(u8 *)buf = 0x30;
837+
838+
return EFI_SUCCESS;
839+
}
840+
841+
static efi_status_t cs_amp_lib_test_get_efi_variable_hp_31(efi_char16_t *name,
842+
efi_guid_t *guid,
843+
unsigned long *size,
844+
void *buf)
845+
{
846+
struct kunit *test = kunit_get_current_test();
847+
848+
if (efi_guidcmp(*guid, HP_SPEAKER_ID_EFI_GUID) ||
849+
memcmp(name, HP_SPEAKER_ID_EFI_NAME, sizeof(HP_SPEAKER_ID_EFI_NAME)))
850+
return EFI_NOT_FOUND;
851+
852+
KUNIT_ASSERT_EQ(test, *size, 1);
853+
*size = 1;
854+
*(u8 *)buf = 0x31;
855+
856+
return EFI_SUCCESS;
857+
}
858+
859+
static void cs_amp_lib_test_spkid_hp_30(struct kunit *test)
860+
{
861+
struct cs_amp_lib_test_priv *priv = test->priv;
862+
struct device *dev = &priv->amp_dev->dev;
863+
864+
kunit_activate_static_stub(test,
865+
cs_amp_test_hooks->get_efi_variable,
866+
cs_amp_lib_test_get_efi_variable_hp_30);
867+
868+
KUNIT_EXPECT_EQ(test, 0, cs_amp_get_vendor_spkid(dev));
869+
}
870+
871+
static void cs_amp_lib_test_spkid_hp_31(struct kunit *test)
872+
{
873+
struct cs_amp_lib_test_priv *priv = test->priv;
874+
struct device *dev = &priv->amp_dev->dev;
875+
876+
kunit_activate_static_stub(test,
877+
cs_amp_test_hooks->get_efi_variable,
878+
cs_amp_lib_test_get_efi_variable_hp_31);
879+
880+
KUNIT_EXPECT_EQ(test, 1, cs_amp_get_vendor_spkid(dev));
881+
}
882+
645883
static int cs_amp_lib_test_case_init(struct kunit *test)
646884
{
647885
struct cs_amp_lib_test_priv *priv;
@@ -722,6 +960,7 @@ static struct kunit_case cs_amp_lib_test_cases[] = {
722960
KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_index_not_found_test),
723961
KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_no_index_test),
724962
KUNIT_CASE(cs_amp_lib_test_get_efi_cal_zero_not_matched_test),
963+
KUNIT_CASE(cs_amp_lib_test_get_hp_efi_cal),
725964
KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_uid_test,
726965
cs_amp_lib_test_get_cal_gen_params),
727966
KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_unchecked_test,
@@ -737,6 +976,15 @@ static struct kunit_case cs_amp_lib_test_cases[] = {
737976
/* Tests for writing calibration data */
738977
KUNIT_CASE(cs_amp_lib_test_write_cal_data_test),
739978

979+
/* Test cases for speaker ID */
980+
KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_not_present),
981+
KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_d0),
982+
KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_d1),
983+
KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_illegal),
984+
KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_oversize),
985+
KUNIT_CASE(cs_amp_lib_test_spkid_hp_30),
986+
KUNIT_CASE(cs_amp_lib_test_spkid_hp_31),
987+
740988
{ } /* terminator */
741989
};
742990

0 commit comments

Comments
 (0)