sdca_device.c 2.8 KB

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