17730bb13SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0 27730bb13SKuninori Morimoto // 37730bb13SKuninori Morimoto // soc-apci.c - support for ACPI enumeration. 47730bb13SKuninori Morimoto // 57730bb13SKuninori Morimoto // Copyright (c) 2013-15, Intel Corporation. 67feb2f78SPierre-Louis Bossart 7261e9082SPaul Gortmaker #include <linux/export.h> 8261e9082SPaul Gortmaker #include <linux/module.h> 97feb2f78SPierre-Louis Bossart #include <sound/soc-acpi.h> 107feb2f78SPierre-Louis Bossart 117feb2f78SPierre-Louis Bossart struct snd_soc_acpi_mach * 127feb2f78SPierre-Louis Bossart snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines) 137feb2f78SPierre-Louis Bossart { 147feb2f78SPierre-Louis Bossart struct snd_soc_acpi_mach *mach; 15a3e620f8SKeyon Jie struct snd_soc_acpi_mach *mach_alt; 167feb2f78SPierre-Louis Bossart 177feb2f78SPierre-Louis Bossart for (mach = machines; mach->id[0]; mach++) { 180d5ea120SJeremy Cline if (acpi_dev_present(mach->id, NULL, -1)) { 19a3e620f8SKeyon Jie if (mach->machine_quirk) { 20a3e620f8SKeyon Jie mach_alt = mach->machine_quirk(mach); 21a3e620f8SKeyon Jie if (!mach_alt) 22a3e620f8SKeyon Jie continue; /* not full match, ignore */ 23a3e620f8SKeyon Jie mach = mach_alt; 24a3e620f8SKeyon Jie } 25a3e620f8SKeyon Jie 267feb2f78SPierre-Louis Bossart return mach; 277feb2f78SPierre-Louis Bossart } 287feb2f78SPierre-Louis Bossart } 297feb2f78SPierre-Louis Bossart return NULL; 307feb2f78SPierre-Louis Bossart } 317feb2f78SPierre-Louis Bossart EXPORT_SYMBOL_GPL(snd_soc_acpi_find_machine); 327feb2f78SPierre-Louis Bossart 337feb2f78SPierre-Louis Bossart static acpi_status snd_soc_acpi_find_package(acpi_handle handle, u32 level, 347feb2f78SPierre-Louis Bossart void *context, void **ret) 357feb2f78SPierre-Louis Bossart { 367feb2f78SPierre-Louis Bossart struct acpi_device *adev; 37*59ce3233SPierre-Louis Bossart acpi_status status; 387feb2f78SPierre-Louis Bossart struct snd_soc_acpi_package_context *pkg_ctx = context; 397feb2f78SPierre-Louis Bossart 407feb2f78SPierre-Louis Bossart pkg_ctx->data_valid = false; 417feb2f78SPierre-Louis Bossart 427feb2f78SPierre-Louis Bossart if (acpi_bus_get_device(handle, &adev)) 437feb2f78SPierre-Louis Bossart return AE_OK; 447feb2f78SPierre-Louis Bossart 457feb2f78SPierre-Louis Bossart if (adev->status.present && adev->status.functional) { 467feb2f78SPierre-Louis Bossart struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 477feb2f78SPierre-Louis Bossart union acpi_object *myobj = NULL; 487feb2f78SPierre-Louis Bossart 497feb2f78SPierre-Louis Bossart status = acpi_evaluate_object_typed(handle, pkg_ctx->name, 507feb2f78SPierre-Louis Bossart NULL, &buffer, 517feb2f78SPierre-Louis Bossart ACPI_TYPE_PACKAGE); 527feb2f78SPierre-Louis Bossart if (ACPI_FAILURE(status)) 537feb2f78SPierre-Louis Bossart return AE_OK; 547feb2f78SPierre-Louis Bossart 557feb2f78SPierre-Louis Bossart myobj = buffer.pointer; 567feb2f78SPierre-Louis Bossart if (!myobj || myobj->package.count != pkg_ctx->length) { 577feb2f78SPierre-Louis Bossart kfree(buffer.pointer); 587feb2f78SPierre-Louis Bossart return AE_OK; 597feb2f78SPierre-Louis Bossart } 607feb2f78SPierre-Louis Bossart 617feb2f78SPierre-Louis Bossart status = acpi_extract_package(myobj, 627feb2f78SPierre-Louis Bossart pkg_ctx->format, pkg_ctx->state); 637feb2f78SPierre-Louis Bossart if (ACPI_FAILURE(status)) { 647feb2f78SPierre-Louis Bossart kfree(buffer.pointer); 657feb2f78SPierre-Louis Bossart return AE_OK; 667feb2f78SPierre-Louis Bossart } 677feb2f78SPierre-Louis Bossart 687feb2f78SPierre-Louis Bossart kfree(buffer.pointer); 697feb2f78SPierre-Louis Bossart pkg_ctx->data_valid = true; 707feb2f78SPierre-Louis Bossart return AE_CTRL_TERMINATE; 717feb2f78SPierre-Louis Bossart } 727feb2f78SPierre-Louis Bossart 737feb2f78SPierre-Louis Bossart return AE_OK; 747feb2f78SPierre-Louis Bossart } 757feb2f78SPierre-Louis Bossart 767feb2f78SPierre-Louis Bossart bool snd_soc_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN], 777feb2f78SPierre-Louis Bossart struct snd_soc_acpi_package_context *ctx) 787feb2f78SPierre-Louis Bossart { 797feb2f78SPierre-Louis Bossart acpi_status status; 807feb2f78SPierre-Louis Bossart 817feb2f78SPierre-Louis Bossart status = acpi_get_devices(hid, snd_soc_acpi_find_package, ctx, NULL); 827feb2f78SPierre-Louis Bossart 837feb2f78SPierre-Louis Bossart if (ACPI_FAILURE(status) || !ctx->data_valid) 847feb2f78SPierre-Louis Bossart return false; 857feb2f78SPierre-Louis Bossart 867feb2f78SPierre-Louis Bossart return true; 877feb2f78SPierre-Louis Bossart } 887feb2f78SPierre-Louis Bossart EXPORT_SYMBOL_GPL(snd_soc_acpi_find_package_from_hid); 897feb2f78SPierre-Louis Bossart 907feb2f78SPierre-Louis Bossart struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) 917feb2f78SPierre-Louis Bossart { 927feb2f78SPierre-Louis Bossart struct snd_soc_acpi_mach *mach = arg; 937feb2f78SPierre-Louis Bossart struct snd_soc_acpi_codecs *codec_list = 947feb2f78SPierre-Louis Bossart (struct snd_soc_acpi_codecs *) mach->quirk_data; 957feb2f78SPierre-Louis Bossart int i; 967feb2f78SPierre-Louis Bossart 977feb2f78SPierre-Louis Bossart if (mach->quirk_data == NULL) 987feb2f78SPierre-Louis Bossart return mach; 997feb2f78SPierre-Louis Bossart 1007feb2f78SPierre-Louis Bossart for (i = 0; i < codec_list->num_codecs; i++) { 1010d5ea120SJeremy Cline if (!acpi_dev_present(codec_list->codecs[i], NULL, -1)) 1027feb2f78SPierre-Louis Bossart return NULL; 1037feb2f78SPierre-Louis Bossart } 1047feb2f78SPierre-Louis Bossart 1057feb2f78SPierre-Louis Bossart return mach; 1067feb2f78SPierre-Louis Bossart } 1077feb2f78SPierre-Louis Bossart EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list); 1087feb2f78SPierre-Louis Bossart 1097feb2f78SPierre-Louis Bossart MODULE_LICENSE("GPL v2"); 1107feb2f78SPierre-Louis Bossart MODULE_DESCRIPTION("ALSA SoC ACPI module"); 111