ASoC: SDCA: Add quirk for incorrect function types for 3 systems

Certain systems have CS42L43 DisCo that claims to conform to version 0.6.28
but uses the function types from the 1.0 spec. Add a quirk as a workaround.

Closes: https://github.com/thesofproject/linux/issues/5515
Cc: stable@vger.kernel.org
Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Link: https://patch.msgid.link/20250901151518.3197941-1-mstrozek@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Maciej Strozek 2025-09-01 16:15:07 +01:00 committed by Mark Brown
parent f1d0260362
commit 28edfaa10c
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
3 changed files with 29 additions and 5 deletions

View File

@ -46,6 +46,7 @@ struct sdca_device_data {
enum sdca_quirk {
SDCA_QUIRKS_RT712_VB,
SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING,
};
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)

View File

@ -7,6 +7,7 @@
*/
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/soundwire/sdw.h>
@ -55,11 +56,30 @@ static bool sdca_device_quirk_rt712_vb(struct sdw_slave *slave)
return false;
}
static bool sdca_device_quirk_skip_func_type_patching(struct sdw_slave *slave)
{
const char *vendor, *sku;
vendor = dmi_get_system_info(DMI_SYS_VENDOR);
sku = dmi_get_system_info(DMI_PRODUCT_SKU);
if (vendor && sku &&
!strcmp(vendor, "Dell Inc.") &&
(!strcmp(sku, "0C62") || !strcmp(sku, "0C63") || !strcmp(sku, "0C6B")) &&
slave->sdca_data.interface_revision == 0x061c &&
slave->id.mfg_id == 0x01fa && slave->id.part_id == 0x4243)
return true;
return false;
}
bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
{
switch (quirk) {
case SDCA_QUIRKS_RT712_VB:
return sdca_device_quirk_rt712_vb(slave);
case SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING:
return sdca_device_quirk_skip_func_type_patching(slave);
default:
break;
}

View File

@ -90,6 +90,7 @@ static int find_sdca_function(struct acpi_device *adev, void *data)
{
struct fwnode_handle *function_node = acpi_fwnode_handle(adev);
struct sdca_device_data *sdca_data = data;
struct sdw_slave *slave = container_of(sdca_data, struct sdw_slave, sdca_data);
struct device *dev = &adev->dev;
struct fwnode_handle *control5; /* used to identify function type */
const char *function_name;
@ -137,11 +138,13 @@ static int find_sdca_function(struct acpi_device *adev, void *data)
return ret;
}
ret = patch_sdca_function_type(sdca_data->interface_revision, &function_type);
if (ret < 0) {
dev_err(dev, "SDCA version %#x invalid function type %d\n",
sdca_data->interface_revision, function_type);
return ret;
if (!sdca_device_quirk_match(slave, SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING)) {
ret = patch_sdca_function_type(sdca_data->interface_revision, &function_type);
if (ret < 0) {
dev_err(dev, "SDCA version %#x invalid function type %d\n",
sdca_data->interface_revision, function_type);
return ret;
}
}
function_name = get_sdca_function_name(function_type);