1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 2 // Copyright(c) 2024 Intel Corporation 3 4 /* 5 * The MIPI SDCA specification is available for public downloads at 6 * https://www.mipi.org/mipi-sdca-v1-0-download 7 */ 8 9 #include <linux/acpi.h> 10 #include <linux/device.h> 11 #include <linux/dmi.h> 12 #include <linux/module.h> 13 #include <linux/property.h> 14 #include <linux/soundwire/sdw.h> 15 #include <sound/sdca.h> 16 #include <sound/sdca_function.h> 17 18 void sdca_lookup_interface_revision(struct sdw_slave *slave) 19 { 20 struct fwnode_handle *fwnode = slave->dev.fwnode; 21 22 /* 23 * if this property is not present, then the sdca_interface_revision will 24 * remain zero, which will be considered as 'not defined' or 'invalid'. 25 */ 26 fwnode_property_read_u32(fwnode, "mipi-sdw-sdca-interface-revision", 27 &slave->sdca_data.interface_revision); 28 } 29 EXPORT_SYMBOL_NS(sdca_lookup_interface_revision, "SND_SOC_SDCA"); 30 31 static void devm_acpi_table_put(void *ptr) 32 { 33 acpi_put_table((struct acpi_table_header *)ptr); 34 } 35 36 void sdca_lookup_swft(struct sdw_slave *slave) 37 { 38 acpi_status status; 39 40 status = acpi_get_table(ACPI_SIG_SWFT, 0, 41 (struct acpi_table_header **)&slave->sdca_data.swft); 42 if (ACPI_FAILURE(status)) 43 dev_info(&slave->dev, "SWFT not available\n"); 44 else 45 devm_add_action_or_reset(&slave->dev, devm_acpi_table_put, 46 &slave->sdca_data.swft); 47 } 48 EXPORT_SYMBOL_NS(sdca_lookup_swft, "SND_SOC_SDCA"); 49 50 static bool sdca_device_quirk_rt712_vb(struct sdw_slave *slave) 51 { 52 struct sdw_slave_id *id = &slave->id; 53 int i; 54 55 /* 56 * The RT712_VA relies on the v06r04 draft, and the 57 * RT712_VB on a more recent v08r01 draft. 58 */ 59 if (slave->sdca_data.interface_revision < 0x0801) 60 return false; 61 62 if (id->mfg_id != 0x025d) 63 return false; 64 65 if (id->part_id != 0x712 && 66 id->part_id != 0x713 && 67 id->part_id != 0x716 && 68 id->part_id != 0x717) 69 return false; 70 71 for (i = 0; i < slave->sdca_data.num_functions; i++) { 72 if (slave->sdca_data.function[i].type == SDCA_FUNCTION_TYPE_SMART_MIC) 73 return true; 74 } 75 76 return false; 77 } 78 79 static bool sdca_device_quirk_skip_func_type_patching(struct sdw_slave *slave) 80 { 81 const char *vendor, *sku; 82 83 vendor = dmi_get_system_info(DMI_SYS_VENDOR); 84 sku = dmi_get_system_info(DMI_PRODUCT_SKU); 85 86 if (vendor && sku && 87 !strcmp(vendor, "Dell Inc.") && 88 (!strcmp(sku, "0C62") || !strcmp(sku, "0C63") || !strcmp(sku, "0C6B")) && 89 slave->sdca_data.interface_revision == 0x061c && 90 slave->id.mfg_id == 0x01fa && slave->id.part_id == 0x4243) 91 return true; 92 93 return false; 94 } 95 96 bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk) 97 { 98 switch (quirk) { 99 case SDCA_QUIRKS_RT712_VB: 100 return sdca_device_quirk_rt712_vb(slave); 101 case SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING: 102 return sdca_device_quirk_skip_func_type_patching(slave); 103 default: 104 break; 105 } 106 return false; 107 } 108 EXPORT_SYMBOL_NS(sdca_device_quirk_match, "SND_SOC_SDCA"); 109