Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+395 -9
+1
include/sound/cs-amp-lib.h
··· 49 49 const struct cirrus_amp_cal_data *data); 50 50 int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_index, 51 51 struct cirrus_amp_cal_data *out_data); 52 + int cs_amp_get_vendor_spkid(struct device *dev); 52 53 53 54 struct cs_amp_test_hooks { 54 55 efi_status_t (*get_efi_variable)(efi_char16_t *name,
+250 -2
sound/soc/codecs/cs-amp-lib-test.c
··· 19 19 #include <linux/random.h> 20 20 #include <sound/cs-amp-lib.h> 21 21 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 + 22 30 KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy, 23 31 struct faux_device *) 24 32 ··· 204 196 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, guid); 205 197 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, size); 206 198 207 - KUNIT_EXPECT_MEMEQ(test, name, expected_name, sizeof(expected_name)); 208 - KUNIT_EXPECT_MEMEQ(test, guid, &expected_guid, sizeof(expected_guid)); 199 + if (memcmp(name, expected_name, sizeof(expected_name)) || 200 + efi_guidcmp(*guid, expected_guid)) 201 + return -EFI_NOT_FOUND; 209 202 210 203 if (!buf) { 211 204 *size = priv->cal_blob->size; ··· 218 209 memcpy(buf, priv->cal_blob, priv->cal_blob->size); 219 210 220 211 return EFI_SUCCESS; 212 + } 213 + 214 + static efi_status_t cs_amp_lib_test_get_hp_cal_efi_variable(efi_char16_t *name, 215 + efi_guid_t *guid, 216 + unsigned long *size, 217 + void *buf) 218 + { 219 + static const efi_char16_t expected_name[] = L"SmartAmpCalibrationData"; 220 + static const efi_guid_t expected_guid = 221 + EFI_GUID(0x53559579, 0x8753, 0x4f5c, 0x91, 0x30, 0xe8, 0x2a, 0xcf, 0xb8, 0xd8, 0x93); 222 + struct kunit *test = kunit_get_current_test(); 223 + struct cs_amp_lib_test_priv *priv = test->priv; 224 + 225 + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, name); 226 + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, guid); 227 + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, size); 228 + 229 + if (memcmp(name, expected_name, sizeof(expected_name)) || 230 + efi_guidcmp(*guid, expected_guid)) 231 + return -EFI_NOT_FOUND; 232 + 233 + if (!buf) { 234 + *size = priv->cal_blob->size; 235 + return EFI_BUFFER_TOO_SMALL; 236 + } 237 + 238 + KUNIT_ASSERT_GE_MSG(test, ksize(buf), priv->cal_blob->size, "Buffer to small"); 239 + 240 + memcpy(buf, priv->cal_blob, priv->cal_blob->size); 241 + 242 + return EFI_SUCCESS; 243 + } 244 + 245 + /* Get cal data block from HP variable. */ 246 + static void cs_amp_lib_test_get_hp_efi_cal(struct kunit *test) 247 + { 248 + struct cs_amp_lib_test_priv *priv = test->priv; 249 + struct cirrus_amp_cal_data result_data; 250 + int ret; 251 + 252 + cs_amp_lib_test_init_dummy_cal_blob(test, 2); 253 + 254 + kunit_activate_static_stub(test, 255 + cs_amp_test_hooks->get_efi_variable, 256 + cs_amp_lib_test_get_hp_cal_efi_variable); 257 + 258 + ret = cs_amp_get_efi_calibration_data(&priv->amp_dev->dev, 0, 0, &result_data); 259 + KUNIT_EXPECT_EQ(test, ret, 0); 260 + 261 + KUNIT_EXPECT_MEMEQ(test, &result_data, &priv->cal_blob->data[0], sizeof(result_data)); 221 262 } 222 263 223 264 /* Get cal data block for a given amp, matched by target UID. */ ··· 701 642 KUNIT_EXPECT_EQ(test, entry->value, data.calStatus); 702 643 } 703 644 645 + static void cs_amp_lib_test_spkid_lenovo_not_present(struct kunit *test) 646 + { 647 + struct cs_amp_lib_test_priv *priv = test->priv; 648 + struct device *dev = &priv->amp_dev->dev; 649 + 650 + kunit_activate_static_stub(test, 651 + cs_amp_test_hooks->get_efi_variable, 652 + cs_amp_lib_test_get_efi_variable_none); 653 + 654 + KUNIT_EXPECT_EQ(test, -ENOENT, cs_amp_get_vendor_spkid(dev)); 655 + } 656 + 657 + static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_d0(efi_char16_t *name, 658 + efi_guid_t *guid, 659 + unsigned long *size, 660 + void *buf) 661 + { 662 + struct kunit *test = kunit_get_current_test(); 663 + 664 + if (efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID) || 665 + memcmp(name, LENOVO_SPEAKER_ID_EFI_NAME, sizeof(LENOVO_SPEAKER_ID_EFI_NAME))) 666 + return EFI_NOT_FOUND; 667 + 668 + KUNIT_ASSERT_EQ(test, *size, 1); 669 + *size = 1; 670 + *(u8 *)buf = 0xd0; 671 + 672 + return EFI_SUCCESS; 673 + } 674 + 675 + static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_d1(efi_char16_t *name, 676 + efi_guid_t *guid, 677 + unsigned long *size, 678 + void *buf) 679 + { 680 + struct kunit *test = kunit_get_current_test(); 681 + 682 + if (efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID) || 683 + memcmp(name, LENOVO_SPEAKER_ID_EFI_NAME, sizeof(LENOVO_SPEAKER_ID_EFI_NAME))) 684 + return EFI_NOT_FOUND; 685 + 686 + KUNIT_ASSERT_EQ(test, *size, 1); 687 + *size = 1; 688 + *(u8 *)buf = 0xd1; 689 + 690 + return EFI_SUCCESS; 691 + } 692 + 693 + static efi_status_t cs_amp_lib_test_get_efi_variable_lenovo_00(efi_char16_t *name, 694 + efi_guid_t *guid, 695 + unsigned long *size, 696 + void *buf) 697 + { 698 + struct kunit *test = kunit_get_current_test(); 699 + 700 + KUNIT_ASSERT_EQ(test, 0, efi_guidcmp(*guid, LENOVO_SPEAKER_ID_EFI_GUID)); 701 + KUNIT_ASSERT_EQ(test, *size, 1); 702 + *size = 1; 703 + *(u8 *)buf = 0; 704 + 705 + return EFI_SUCCESS; 706 + } 707 + 708 + static void cs_amp_lib_test_spkid_lenovo_d0(struct kunit *test) 709 + { 710 + struct cs_amp_lib_test_priv *priv = test->priv; 711 + struct device *dev = &priv->amp_dev->dev; 712 + 713 + kunit_activate_static_stub(test, 714 + cs_amp_test_hooks->get_efi_variable, 715 + cs_amp_lib_test_get_efi_variable_lenovo_d0); 716 + 717 + KUNIT_EXPECT_EQ(test, 0, cs_amp_get_vendor_spkid(dev)); 718 + } 719 + 720 + static void cs_amp_lib_test_spkid_lenovo_d1(struct kunit *test) 721 + { 722 + struct cs_amp_lib_test_priv *priv = test->priv; 723 + struct device *dev = &priv->amp_dev->dev; 724 + 725 + kunit_activate_static_stub(test, 726 + cs_amp_test_hooks->get_efi_variable, 727 + cs_amp_lib_test_get_efi_variable_lenovo_d1); 728 + 729 + KUNIT_EXPECT_EQ(test, 1, cs_amp_get_vendor_spkid(dev)); 730 + } 731 + 732 + static void cs_amp_lib_test_spkid_lenovo_illegal(struct kunit *test) 733 + { 734 + struct cs_amp_lib_test_priv *priv = test->priv; 735 + struct device *dev = &priv->amp_dev->dev; 736 + 737 + kunit_activate_static_stub(test, 738 + cs_amp_test_hooks->get_efi_variable, 739 + cs_amp_lib_test_get_efi_variable_lenovo_00); 740 + 741 + KUNIT_EXPECT_LT(test, cs_amp_get_vendor_spkid(dev), 0); 742 + } 743 + 744 + static efi_status_t cs_amp_lib_test_get_efi_variable_buf_too_small(efi_char16_t *name, 745 + efi_guid_t *guid, 746 + unsigned long *size, 747 + void *buf) 748 + { 749 + return EFI_BUFFER_TOO_SMALL; 750 + } 751 + 752 + static void cs_amp_lib_test_spkid_lenovo_oversize(struct kunit *test) 753 + { 754 + struct cs_amp_lib_test_priv *priv = test->priv; 755 + struct device *dev = &priv->amp_dev->dev; 756 + 757 + kunit_activate_static_stub(test, 758 + cs_amp_test_hooks->get_efi_variable, 759 + cs_amp_lib_test_get_efi_variable_buf_too_small); 760 + 761 + KUNIT_EXPECT_LT(test, cs_amp_get_vendor_spkid(dev), 0); 762 + } 763 + 764 + static efi_status_t cs_amp_lib_test_get_efi_variable_hp_30(efi_char16_t *name, 765 + efi_guid_t *guid, 766 + unsigned long *size, 767 + void *buf) 768 + { 769 + struct kunit *test = kunit_get_current_test(); 770 + 771 + if (efi_guidcmp(*guid, HP_SPEAKER_ID_EFI_GUID) || 772 + memcmp(name, HP_SPEAKER_ID_EFI_NAME, sizeof(HP_SPEAKER_ID_EFI_NAME))) 773 + return EFI_NOT_FOUND; 774 + 775 + KUNIT_ASSERT_EQ(test, *size, 1); 776 + *size = 1; 777 + *(u8 *)buf = 0x30; 778 + 779 + return EFI_SUCCESS; 780 + } 781 + 782 + static efi_status_t cs_amp_lib_test_get_efi_variable_hp_31(efi_char16_t *name, 783 + efi_guid_t *guid, 784 + unsigned long *size, 785 + void *buf) 786 + { 787 + struct kunit *test = kunit_get_current_test(); 788 + 789 + if (efi_guidcmp(*guid, HP_SPEAKER_ID_EFI_GUID) || 790 + memcmp(name, HP_SPEAKER_ID_EFI_NAME, sizeof(HP_SPEAKER_ID_EFI_NAME))) 791 + return EFI_NOT_FOUND; 792 + 793 + KUNIT_ASSERT_EQ(test, *size, 1); 794 + *size = 1; 795 + *(u8 *)buf = 0x31; 796 + 797 + return EFI_SUCCESS; 798 + } 799 + 800 + static void cs_amp_lib_test_spkid_hp_30(struct kunit *test) 801 + { 802 + struct cs_amp_lib_test_priv *priv = test->priv; 803 + struct device *dev = &priv->amp_dev->dev; 804 + 805 + kunit_activate_static_stub(test, 806 + cs_amp_test_hooks->get_efi_variable, 807 + cs_amp_lib_test_get_efi_variable_hp_30); 808 + 809 + KUNIT_EXPECT_EQ(test, 0, cs_amp_get_vendor_spkid(dev)); 810 + } 811 + 812 + static void cs_amp_lib_test_spkid_hp_31(struct kunit *test) 813 + { 814 + struct cs_amp_lib_test_priv *priv = test->priv; 815 + struct device *dev = &priv->amp_dev->dev; 816 + 817 + kunit_activate_static_stub(test, 818 + cs_amp_test_hooks->get_efi_variable, 819 + cs_amp_lib_test_get_efi_variable_hp_31); 820 + 821 + KUNIT_EXPECT_EQ(test, 1, cs_amp_get_vendor_spkid(dev)); 822 + } 823 + 704 824 static int cs_amp_lib_test_case_init(struct kunit *test) 705 825 { 706 826 struct cs_amp_lib_test_priv *priv; ··· 960 722 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_index_not_found_test), 961 723 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_no_index_test), 962 724 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_zero_not_matched_test), 725 + KUNIT_CASE(cs_amp_lib_test_get_hp_efi_cal), 963 726 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_uid_test, 964 727 cs_amp_lib_test_get_cal_gen_params), 965 728 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_unchecked_test, ··· 975 736 976 737 /* Tests for writing calibration data */ 977 738 KUNIT_CASE(cs_amp_lib_test_write_cal_data_test), 739 + 740 + /* Test cases for speaker ID */ 741 + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_not_present), 742 + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_d0), 743 + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_d1), 744 + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_illegal), 745 + KUNIT_CASE(cs_amp_lib_test_spkid_lenovo_oversize), 746 + KUNIT_CASE(cs_amp_lib_test_spkid_hp_30), 747 + KUNIT_CASE(cs_amp_lib_test_spkid_hp_31), 978 748 979 749 { } /* terminator */ 980 750 };
+133 -6
sound/soc/codecs/cs-amp-lib.c
··· 16 16 #include <linux/types.h> 17 17 #include <sound/cs-amp-lib.h> 18 18 19 - #define CS_AMP_CAL_GUID \ 19 + #define CIRRUS_LOGIC_CALIBRATION_EFI_NAME L"CirrusSmartAmpCalibrationData" 20 + #define CIRRUS_LOGIC_CALIBRATION_EFI_GUID \ 20 21 EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3) 21 22 22 - #define CS_AMP_CAL_NAME L"CirrusSmartAmpCalibrationData" 23 + #define LENOVO_SPEAKER_ID_EFI_NAME L"SdwSpeaker" 24 + #define LENOVO_SPEAKER_ID_EFI_GUID \ 25 + EFI_GUID(0x48df970e, 0xe27f, 0x460a, 0xb5, 0x86, 0x77, 0x19, 0x80, 0x1d, 0x92, 0x82) 26 + 27 + #define HP_SPEAKER_ID_EFI_NAME L"HPSpeakerID" 28 + #define HP_SPEAKER_ID_EFI_GUID \ 29 + EFI_GUID(0xc49593a4, 0xd099, 0x419b, 0xa2, 0xc3, 0x67, 0xe9, 0x80, 0xe6, 0x1d, 0x1e) 30 + 31 + #define HP_CALIBRATION_EFI_NAME L"SmartAmpCalibrationData" 32 + #define HP_CALIBRATION_EFI_GUID \ 33 + EFI_GUID(0x53559579, 0x8753, 0x4f5c, 0x91, 0x30, 0xe8, 0x2a, 0xcf, 0xb8, 0xd8, 0x93) 34 + 35 + static const struct cs_amp_lib_cal_efivar { 36 + efi_char16_t *name; 37 + efi_guid_t *guid; 38 + } cs_amp_lib_cal_efivars[] = { 39 + { 40 + .name = HP_CALIBRATION_EFI_NAME, 41 + .guid = &HP_CALIBRATION_EFI_GUID, 42 + }, 43 + { 44 + .name = CIRRUS_LOGIC_CALIBRATION_EFI_NAME, 45 + .guid = &CIRRUS_LOGIC_CALIBRATION_EFI_GUID, 46 + }, 47 + }; 23 48 24 49 static int cs_amp_write_cal_coeff(struct cs_dsp *dsp, 25 50 const struct cirrus_amp_cal_controls *controls, ··· 140 115 return EFI_NOT_FOUND; 141 116 } 142 117 118 + static int cs_amp_convert_efi_status(efi_status_t status) 119 + { 120 + switch (status) { 121 + case EFI_SUCCESS: 122 + return 0; 123 + case EFI_NOT_FOUND: 124 + return -ENOENT; 125 + case EFI_BUFFER_TOO_SMALL: 126 + return -EFBIG; 127 + case EFI_UNSUPPORTED: 128 + case EFI_ACCESS_DENIED: 129 + case EFI_SECURITY_VIOLATION: 130 + return -EACCES; 131 + default: 132 + return -EIO; 133 + } 134 + } 135 + 143 136 static struct cirrus_amp_efi_data *cs_amp_get_cal_efi_buffer(struct device *dev) 144 137 { 145 138 struct cirrus_amp_efi_data *efi_data; 146 139 unsigned long data_size = 0; 147 140 u8 *data; 148 141 efi_status_t status; 149 - int ret; 142 + int i, ret; 150 143 151 - /* Get real size of UEFI variable */ 152 - status = cs_amp_get_efi_variable(CS_AMP_CAL_NAME, &CS_AMP_CAL_GUID, &data_size, NULL); 144 + /* Find EFI variable and get size */ 145 + for (i = 0; i < ARRAY_SIZE(cs_amp_lib_cal_efivars); i++) { 146 + status = cs_amp_get_efi_variable(cs_amp_lib_cal_efivars[i].name, 147 + cs_amp_lib_cal_efivars[i].guid, 148 + &data_size, NULL); 149 + if (status == EFI_BUFFER_TOO_SMALL) 150 + break; 151 + } 152 + 153 153 if (status != EFI_BUFFER_TOO_SMALL) 154 154 return ERR_PTR(-ENOENT); 155 155 ··· 188 138 if (!data) 189 139 return ERR_PTR(-ENOMEM); 190 140 191 - status = cs_amp_get_efi_variable(CS_AMP_CAL_NAME, &CS_AMP_CAL_GUID, &data_size, data); 141 + status = cs_amp_get_efi_variable(cs_amp_lib_cal_efivars[i].name, 142 + cs_amp_lib_cal_efivars[i].guid, 143 + &data_size, data); 192 144 if (status != EFI_SUCCESS) { 193 145 ret = -EINVAL; 194 146 goto err; ··· 324 272 return -ENOENT; 325 273 } 326 274 EXPORT_SYMBOL_NS_GPL(cs_amp_get_efi_calibration_data, "SND_SOC_CS_AMP_LIB"); 275 + 276 + struct cs_amp_spkid_efi { 277 + efi_char16_t *name; 278 + efi_guid_t *guid; 279 + u8 values[2]; 280 + }; 281 + 282 + static int cs_amp_get_efi_byte_spkid(struct device *dev, const struct cs_amp_spkid_efi *info) 283 + { 284 + efi_status_t status; 285 + unsigned long size; 286 + u8 spkid; 287 + int i, ret; 288 + 289 + size = sizeof(spkid); 290 + status = cs_amp_get_efi_variable(info->name, info->guid, &size, &spkid); 291 + ret = cs_amp_convert_efi_status(status); 292 + if (ret < 0) 293 + return ret; 294 + 295 + if (size == 0) 296 + return -ENOENT; 297 + 298 + for (i = 0; i < ARRAY_SIZE(info->values); i++) { 299 + if (info->values[i] == spkid) 300 + return i; 301 + } 302 + 303 + dev_err(dev, "EFI speaker ID bad value %#x\n", spkid); 304 + 305 + return -EINVAL; 306 + } 307 + 308 + static const struct cs_amp_spkid_efi cs_amp_spkid_byte_types[] = { 309 + { 310 + .name = LENOVO_SPEAKER_ID_EFI_NAME, 311 + .guid = &LENOVO_SPEAKER_ID_EFI_GUID, 312 + .values = { 0xd0, 0xd1 }, 313 + }, 314 + { 315 + .name = HP_SPEAKER_ID_EFI_NAME, 316 + .guid = &HP_SPEAKER_ID_EFI_GUID, 317 + .values = { 0x30, 0x31 }, 318 + }, 319 + }; 320 + 321 + /** 322 + * cs_amp_get_vendor_spkid - get a speaker ID from vendor-specific storage 323 + * @dev: pointer to struct device 324 + * 325 + * Known vendor-specific methods of speaker ID are checked and if one is 326 + * found its speaker ID value is returned. 327 + * 328 + * Return: >=0 is a valid speaker ID. -ENOENT if a vendor-specific method 329 + * was not found. -EACCES if the vendor-specific storage could not 330 + * be read. Other error values indicate that the data from the 331 + * vendor-specific storage was found but could not be understood. 332 + */ 333 + int cs_amp_get_vendor_spkid(struct device *dev) 334 + { 335 + int i, ret; 336 + 337 + if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE) && 338 + !IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST)) 339 + return -ENOENT; 340 + 341 + for (i = 0; i < ARRAY_SIZE(cs_amp_spkid_byte_types); i++) { 342 + ret = cs_amp_get_efi_byte_spkid(dev, &cs_amp_spkid_byte_types[i]); 343 + if (ret != -ENOENT) 344 + return ret; 345 + } 346 + 347 + return -ENOENT; 348 + } 349 + EXPORT_SYMBOL_NS_GPL(cs_amp_get_vendor_spkid, "SND_SOC_CS_AMP_LIB"); 327 350 328 351 static const struct cs_amp_test_hooks cs_amp_test_hook_ptrs = { 329 352 .get_efi_variable = cs_amp_get_efi_variable,
+11 -1
sound/soc/codecs/cs35l56-shared.c
··· 1054 1054 u32 speaker_id; 1055 1055 int i, ret; 1056 1056 1057 - /* Attempt to read the speaker type from a device property first */ 1057 + /* Check for vendor-specific speaker ID method */ 1058 + ret = cs_amp_get_vendor_spkid(cs35l56_base->dev); 1059 + if (ret >= 0) { 1060 + dev_dbg(cs35l56_base->dev, "Vendor Speaker ID = %d\n", ret); 1061 + return ret; 1062 + } else if (ret != -ENOENT) { 1063 + dev_err(cs35l56_base->dev, "Error getting vendor Speaker ID: %d\n", ret); 1064 + return ret; 1065 + } 1066 + 1067 + /* Attempt to read the speaker type from a device property */ 1058 1068 ret = device_property_read_u32(cs35l56_base->dev, "cirrus,speaker-id", &speaker_id); 1059 1069 if (!ret) { 1060 1070 dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id);