[PATCH v2 2/3] ASoC: tas2783: also look for calibration data under the OEM GUID

jml <[email protected]>
Newsgroups gmane.linux.sound
Message-ID <[email protected]>
tas2783_update_calibdata() looks the SmartAmpCalibrationData UEFI
variable up under a single vendor GUID. At least one OEM stores the very
same payload under a different GUID: on the HP OmniBook X Flip
14-kc0xxx the variable is named SmartAmpCalibrationData but sits under
53559579-8753-4f5c-9130-e82acfb8d893.

efi.get_variable() matches on name *and* GUID, so the lookup fails, the
driver takes the silent dev_dbg("No calibration data in UEFI") path, and
the amplifiers run on generic defaults. The factory data is present and
valid - magic 2783, spk_count 2, CRC32 verified, per-speaker records
carrying the unique_ids of the two amplifiers fitted - it is simply
never read. Audibly this shows up as distortion at higher volumes, since
the protection algorithm has no real R0/TLim values for the drivers.

Try both GUIDs before giving up.

Signed-off-by: jml <[email protected]>
---
 sound/soc/codecs/tas2783-sdw.c | 52 +++++++++++++++++++++++-----------
 1 file changed, 35 insertions(+), 17 deletions(-)

diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c
index eaebb0ebb..2ca634a6e 100644
--- a/sound/soc/codecs/tas2783-sdw.c
+++ b/sound/soc/codecs/tas2783-sdw.c
@@ -46,6 +46,15 @@
 #define TAS2783_PROBE_TIMEOUT 5000
 #define TAS2783_CALI_GUID EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, \
 				   0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92)
+/*
+ * Some OEMs store the same SmartAmpCalibrationData payload under a different
+ * vendor GUID. Seen on the HP OmniBook X Flip 14-kc0xxx (board 8EA1): the
+ * variable name matches but the GUID does not, so the factory per-speaker
+ * calibration was silently ignored and the protection algorithm ran on
+ * defaults.
+ */
+#define TAS2783_CALI_GUID_ALT EFI_GUID(0x53559579, 0x8753, 0x4f5c, 0x91, \
+				       0x30, 0xe8, 0x2a, 0xcf, 0xb8, 0xd8, 0x93)
 
 static const u32 tas2783_cali_reg[] = {
 	TAS2783_CAL_R0,
@@ -702,8 +711,10 @@ static void tas2783_set_calib_params_to_device(struct tas2783_prv *tas_dev, u32
 
 static s32 tas2783_update_calibdata(struct tas2783_prv *tas_dev)
 {
-	efi_guid_t efi_guid = TAS2783_CALI_GUID;
-	u32 attr, i, *tmp_val;
+	static const efi_guid_t efi_guids[] = {
+		TAS2783_CALI_GUID, TAS2783_CALI_GUID_ALT };
+	efi_guid_t efi_guid;
+	u32 attr, i, g, *tmp_val;
 	unsigned long size;
 	s32 ret;
 	efi_status_t status;
@@ -717,22 +728,29 @@ static s32 tas2783_update_calibdata(struct tas2783_prv *tas_dev)
 	 * In some cases, the calibration is performed in Windows,
 	 * and data was saved in UEFI. Linux can access it.
 	 */
-	for (i = 0; i < ARRAY_SIZE(efi_names); i++) {
-		size = 0;
-		status = efi.get_variable(efi_names[i], &efi_guid, &attr,
-					  &size, NULL);
-		if (size > TAS2783_CALIB_DATA_SZ) {
-			dev_err(tas_dev->dev, "cali data too large\n");
-			break;
-		}
-
-		tas_dev->cali_data.read_sz = size;
-		if (status == EFI_BUFFER_TOO_SMALL) {
+	status = EFI_NOT_FOUND;
+	for (g = 0; g < ARRAY_SIZE(efi_guids); g++) {
+		efi_guid = efi_guids[g];
+		for (i = 0; i < ARRAY_SIZE(efi_names); i++) {
+			size = 0;
 			status = efi.get_variable(efi_names[i], &efi_guid, &attr,
-							&tas_dev->cali_data.read_sz,
-							tas_dev->cali_data.data);
-			dev_dbg(tas_dev->dev, "cali get %lu bytes result:%ld\n",
-				tas_dev->cali_data.read_sz, status);
+						  &size, NULL);
+			if (size > TAS2783_CALIB_DATA_SZ) {
+				dev_err(tas_dev->dev, "cali data too large\n");
+				status = EFI_NOT_FOUND;
+				break;
+			}
+
+			tas_dev->cali_data.read_sz = size;
+			if (status == EFI_BUFFER_TOO_SMALL) {
+				status = efi.get_variable(efi_names[i], &efi_guid, &attr,
+							  &tas_dev->cali_data.read_sz,
+							  tas_dev->cali_data.data);
+				dev_dbg(tas_dev->dev, "cali get %lu bytes result:%ld\n",
+					tas_dev->cali_data.read_sz, status);
+			}
+			if (status == EFI_SUCCESS)
+				break;
 		}
 		if (status == EFI_SUCCESS)
 			break;
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.