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