[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