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