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