soc-acpi.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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. struct snd_soc_acpi_mach *
  10. snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines)
  11. {
  12. struct snd_soc_acpi_mach *mach;
  13. struct snd_soc_acpi_mach *mach_alt;
  14. for (mach = machines; mach->id[0]; mach++) {
  15. if (acpi_dev_present(mach->id, NULL, -1)) {
  16. if (mach->machine_quirk) {
  17. mach_alt = mach->machine_quirk(mach);
  18. if (!mach_alt)
  19. continue; /* not full match, ignore */
  20. mach = mach_alt;
  21. }
  22. return mach;
  23. }
  24. }
  25. return NULL;
  26. }
  27. EXPORT_SYMBOL_GPL(snd_soc_acpi_find_machine);
  28. static acpi_status snd_soc_acpi_find_package(acpi_handle handle, u32 level,
  29. void *context, void **ret)
  30. {
  31. struct acpi_device *adev;
  32. acpi_status status = AE_OK;
  33. struct snd_soc_acpi_package_context *pkg_ctx = context;
  34. pkg_ctx->data_valid = false;
  35. if (acpi_bus_get_device(handle, &adev))
  36. return AE_OK;
  37. if (adev->status.present && adev->status.functional) {
  38. struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
  39. union acpi_object *myobj = NULL;
  40. status = acpi_evaluate_object_typed(handle, pkg_ctx->name,
  41. NULL, &buffer,
  42. ACPI_TYPE_PACKAGE);
  43. if (ACPI_FAILURE(status))
  44. return AE_OK;
  45. myobj = buffer.pointer;
  46. if (!myobj || myobj->package.count != pkg_ctx->length) {
  47. kfree(buffer.pointer);
  48. return AE_OK;
  49. }
  50. status = acpi_extract_package(myobj,
  51. pkg_ctx->format, pkg_ctx->state);
  52. if (ACPI_FAILURE(status)) {
  53. kfree(buffer.pointer);
  54. return AE_OK;
  55. }
  56. kfree(buffer.pointer);
  57. pkg_ctx->data_valid = true;
  58. return AE_CTRL_TERMINATE;
  59. }
  60. return AE_OK;
  61. }
  62. bool snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
  63. struct snd_soc_acpi_package_context *ctx)
  64. {
  65. acpi_status status;
  66. status = acpi_get_devices(hid, snd_soc_acpi_find_package, ctx, NULL);
  67. if (ACPI_FAILURE(status) || !ctx->data_valid)
  68. return false;
  69. return true;
  70. }
  71. EXPORT_SYMBOL_GPL(snd_soc_acpi_find_package_from_hid);
  72. struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
  73. {
  74. struct snd_soc_acpi_mach *mach = arg;
  75. struct snd_soc_acpi_codecs *codec_list =
  76. (struct snd_soc_acpi_codecs *) mach->quirk_data;
  77. int i;
  78. if (mach->quirk_data == NULL)
  79. return mach;
  80. for (i = 0; i < codec_list->num_codecs; i++) {
  81. if (!acpi_dev_present(codec_list->codecs[i], NULL, -1))
  82. return NULL;
  83. }
  84. return mach;
  85. }
  86. EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list);
  87. MODULE_LICENSE("GPL v2");
  88. MODULE_DESCRIPTION("ALSA SoC ACPI module");