1 /* 2 * soc-apci.c - support for ACPI enumeration. 3 * 4 * Copyright (c) 2013-15, Intel Corporation. 5 * 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms and conditions of the GNU General Public License, 9 * version 2, as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 * more details. 15 */ 16 17 #include <sound/soc-acpi.h> 18 19 struct snd_soc_acpi_mach * 20 snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines) 21 { 22 struct snd_soc_acpi_mach *mach; 23 24 for (mach = machines; mach->id[0]; mach++) { 25 if (acpi_dev_present(mach->id, NULL, -1)) { 26 if (mach->machine_quirk) 27 mach = mach->machine_quirk(mach); 28 return mach; 29 } 30 } 31 return NULL; 32 } 33 EXPORT_SYMBOL_GPL(snd_soc_acpi_find_machine); 34 35 static acpi_status snd_soc_acpi_find_package(acpi_handle handle, u32 level, 36 void *context, void **ret) 37 { 38 struct acpi_device *adev; 39 acpi_status status = AE_OK; 40 struct snd_soc_acpi_package_context *pkg_ctx = context; 41 42 pkg_ctx->data_valid = false; 43 44 if (acpi_bus_get_device(handle, &adev)) 45 return AE_OK; 46 47 if (adev->status.present && adev->status.functional) { 48 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 49 union acpi_object *myobj = NULL; 50 51 status = acpi_evaluate_object_typed(handle, pkg_ctx->name, 52 NULL, &buffer, 53 ACPI_TYPE_PACKAGE); 54 if (ACPI_FAILURE(status)) 55 return AE_OK; 56 57 myobj = buffer.pointer; 58 if (!myobj || myobj->package.count != pkg_ctx->length) { 59 kfree(buffer.pointer); 60 return AE_OK; 61 } 62 63 status = acpi_extract_package(myobj, 64 pkg_ctx->format, pkg_ctx->state); 65 if (ACPI_FAILURE(status)) { 66 kfree(buffer.pointer); 67 return AE_OK; 68 } 69 70 kfree(buffer.pointer); 71 pkg_ctx->data_valid = true; 72 return AE_CTRL_TERMINATE; 73 } 74 75 return AE_OK; 76 } 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 83 status = acpi_get_devices(hid, snd_soc_acpi_find_package, ctx, NULL); 84 85 if (ACPI_FAILURE(status) || !ctx->data_valid) 86 return false; 87 88 return true; 89 } 90 EXPORT_SYMBOL_GPL(snd_soc_acpi_find_package_from_hid); 91 92 struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) 93 { 94 struct snd_soc_acpi_mach *mach = arg; 95 struct snd_soc_acpi_codecs *codec_list = 96 (struct snd_soc_acpi_codecs *) mach->quirk_data; 97 int i; 98 99 if (mach->quirk_data == NULL) 100 return mach; 101 102 for (i = 0; i < codec_list->num_codecs; i++) { 103 if (!acpi_dev_present(codec_list->codecs[i], NULL, -1)) 104 return NULL; 105 } 106 107 return mach; 108 } 109 EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list); 110 111 MODULE_LICENSE("GPL v2"); 112 MODULE_DESCRIPTION("ALSA SoC ACPI module"); 113