soc-acpi.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // soc-apci.c - support for ACPI enumeration.
  4. //
  5. // Copyright (c) 2013-15, Intel Corporation.
  6. #include <linux/export.h>
  7. #include <linux/module.h>
  8. #include <sound/soc-acpi.h>
  9. static bool snd_soc_acpi_id_present(struct snd_soc_acpi_mach *machine)
  10. {
  11. const struct snd_soc_acpi_codecs *comp_ids = machine->comp_ids;
  12. int i;
  13. if (machine->id[0]) {
  14. if (acpi_dev_present(machine->id, NULL, -1))
  15. return true;
  16. }
  17. if (comp_ids) {
  18. for (i = 0; i < comp_ids->num_codecs; i++) {
  19. if (acpi_dev_present(comp_ids->codecs[i], NULL, -1)) {
  20. strscpy(machine->id, comp_ids->codecs[i], ACPI_ID_LEN);
  21. return true;
  22. }
  23. }
  24. }
  25. return false;
  26. }
  27. struct snd_soc_acpi_mach *
  28. snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines)
  29. {
  30. struct snd_soc_acpi_mach *mach;
  31. struct snd_soc_acpi_mach *mach_alt;
  32. for (mach = machines; mach->id[0] || mach->comp_ids; mach++) {
  33. if (snd_soc_acpi_id_present(mach)) {
  34. if (mach->machine_quirk) {
  35. mach_alt = mach->machine_quirk(mach);
  36. if (!mach_alt)
  37. continue; /* not full match, ignore */
  38. mach = mach_alt;
  39. }
  40. return mach;
  41. }
  42. }
  43. return NULL;
  44. }
  45. EXPORT_SYMBOL_GPL(snd_soc_acpi_find_machine);
  46. static acpi_status snd_soc_acpi_find_package(acpi_handle handle, u32 level,
  47. void *context, void **ret)
  48. {
  49. struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
  50. acpi_status status;
  51. struct snd_soc_acpi_package_context *pkg_ctx = context;
  52. pkg_ctx->data_valid = false;
  53. if (adev && adev->status.present && adev->status.functional) {
  54. struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
  55. union acpi_object *myobj = NULL;
  56. status = acpi_evaluate_object_typed(handle, pkg_ctx->name,
  57. NULL, &buffer,
  58. ACPI_TYPE_PACKAGE);
  59. if (ACPI_FAILURE(status))
  60. return AE_OK;
  61. myobj = buffer.pointer;
  62. if (!myobj || myobj->package.count != pkg_ctx->length) {
  63. kfree(buffer.pointer);
  64. return AE_OK;
  65. }
  66. status = acpi_extract_package(myobj,
  67. pkg_ctx->format, pkg_ctx->state);
  68. if (ACPI_FAILURE(status)) {
  69. kfree(buffer.pointer);
  70. return AE_OK;
  71. }
  72. kfree(buffer.pointer);
  73. pkg_ctx->data_valid = true;
  74. return AE_CTRL_TERMINATE;
  75. }
  76. return AE_OK;
  77. }
  78. bool snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
  79. struct snd_soc_acpi_package_context *ctx)
  80. {
  81. acpi_status status;
  82. status = acpi_get_devices(hid, snd_soc_acpi_find_package, ctx, NULL);
  83. if (ACPI_FAILURE(status) || !ctx->data_valid)
  84. return false;
  85. return true;
  86. }
  87. EXPORT_SYMBOL_GPL(snd_soc_acpi_find_package_from_hid);
  88. struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
  89. {
  90. struct snd_soc_acpi_mach *mach = arg;
  91. struct snd_soc_acpi_codecs *codec_list =
  92. (struct snd_soc_acpi_codecs *) mach->quirk_data;
  93. int i;
  94. if (mach->quirk_data == NULL)
  95. return mach;
  96. for (i = 0; i < codec_list->num_codecs; i++) {
  97. if (!acpi_dev_present(codec_list->codecs[i], NULL, -1))
  98. return NULL;
  99. }
  100. return mach;
  101. }
  102. EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list);
  103. MODULE_LICENSE("GPL v2");
  104. MODULE_DESCRIPTION("ALSA SoC ACPI module");