linux/sound/soc/soc-acpi.c
<<
>>
Prefs
   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
  11struct snd_soc_acpi_mach *
  12snd_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}
  31EXPORT_SYMBOL_GPL(snd_soc_acpi_find_machine);
  32
  33static 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
  76bool 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}
  88EXPORT_SYMBOL_GPL(snd_soc_acpi_find_package_from_hid);
  89
  90struct 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}
 107EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list);
 108
 109MODULE_LICENSE("GPL v2");
 110MODULE_DESCRIPTION("ALSA SoC ACPI module");
 111