1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 // Copyright(c) 2024 Intel Corporation
5 * The MIPI SDCA specification is available for public downloads at
6 * https://www.mipi.org/mipi-sdca-v1-0-download
9 #include <linux/acpi.h>
10 #include <linux/soundwire/sdw.h>
11 #include <sound/sdca.h>
12 #include <sound/sdca_function.h>
14 static int patch_sdca_function_type(struct device
*dev
,
15 u32 interface_revision
,
17 const char **function_name
)
19 unsigned long function_type_patch
= 0;
22 * Unfortunately early SDCA specifications used different indices for Functions,
23 * for backwards compatibility we have to reorder the values found
25 if (interface_revision
>= 0x0801)
26 goto skip_early_draft_order
;
28 switch (*function_type
) {
30 function_type_patch
= SDCA_FUNCTION_TYPE_SMART_AMP
;
33 function_type_patch
= SDCA_FUNCTION_TYPE_SMART_MIC
;
36 function_type_patch
= SDCA_FUNCTION_TYPE_SPEAKER_MIC
;
39 function_type_patch
= SDCA_FUNCTION_TYPE_UAJ
;
42 function_type_patch
= SDCA_FUNCTION_TYPE_RJ
;
45 function_type_patch
= SDCA_FUNCTION_TYPE_HID
;
48 dev_warn(dev
, "%s: SDCA version %#x unsupported function type %d, skipped\n",
49 __func__
, interface_revision
, *function_type
);
53 skip_early_draft_order
:
54 if (function_type_patch
)
55 *function_type
= function_type_patch
;
57 /* now double-check the values */
58 switch (*function_type
) {
59 case SDCA_FUNCTION_TYPE_SMART_AMP
:
60 *function_name
= SDCA_FUNCTION_TYPE_SMART_AMP_NAME
;
62 case SDCA_FUNCTION_TYPE_SMART_MIC
:
63 *function_name
= SDCA_FUNCTION_TYPE_SMART_MIC_NAME
;
65 case SDCA_FUNCTION_TYPE_UAJ
:
66 *function_name
= SDCA_FUNCTION_TYPE_UAJ_NAME
;
68 case SDCA_FUNCTION_TYPE_HID
:
69 *function_name
= SDCA_FUNCTION_TYPE_HID_NAME
;
71 case SDCA_FUNCTION_TYPE_SIMPLE_AMP
:
72 case SDCA_FUNCTION_TYPE_SIMPLE_MIC
:
73 case SDCA_FUNCTION_TYPE_SPEAKER_MIC
:
74 case SDCA_FUNCTION_TYPE_RJ
:
75 case SDCA_FUNCTION_TYPE_IMP_DEF
:
76 dev_warn(dev
, "%s: found unsupported SDCA function type %d, skipped\n",
77 __func__
, *function_type
);
80 dev_err(dev
, "%s: found invalid SDCA function type %d, skipped\n",
81 __func__
, *function_type
);
85 dev_info(dev
, "%s: found SDCA function %s (type %d)\n",
86 __func__
, *function_name
, *function_type
);
91 static int find_sdca_function(struct acpi_device
*adev
, void *data
)
93 struct fwnode_handle
*function_node
= acpi_fwnode_handle(adev
);
94 struct sdca_device_data
*sdca_data
= data
;
95 struct device
*dev
= &adev
->dev
;
96 struct fwnode_handle
*control5
; /* used to identify function type */
97 const char *function_name
;
103 if (sdca_data
->num_functions
>= SDCA_MAX_FUNCTION_COUNT
) {
104 dev_err(dev
, "%s: maximum number of functions exceeded\n", __func__
);
109 * The number of functions cannot exceed 8, we could use
110 * acpi_get_local_address() but the value is stored as u64 so
111 * we might as well avoid casts and intermediate levels
113 ret
= acpi_get_local_u64_address(adev
->handle
, &addr
);
118 dev_err(dev
, "%s: no addr\n", __func__
);
123 * Extracting the topology type for an SDCA function is a
124 * convoluted process.
125 * The Function type is only visible as a result of a read
126 * from a control. In theory this would mean reading from the hardware,
127 * but the SDCA/DisCo specs defined the notion of "DC value" - a constant
128 * represented with a DSD subproperty.
129 * Drivers have to query the properties for the control
130 * SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY (0x05)
132 control5
= fwnode_get_named_child_node(function_node
,
133 "mipi-sdca-control-0x5-subproperties");
137 ret
= fwnode_property_read_u32(control5
, "mipi-sdca-control-dc-value",
140 fwnode_handle_put(control5
);
143 dev_err(dev
, "%s: the function type can only be determined from ACPI information\n",
148 ret
= patch_sdca_function_type(dev
, sdca_data
->interface_revision
,
149 &function_type
, &function_name
);
154 func_index
= sdca_data
->num_functions
;
155 sdca_data
->sdca_func
[func_index
].adr
= addr
;
156 sdca_data
->sdca_func
[func_index
].type
= function_type
;
157 sdca_data
->sdca_func
[func_index
].name
= function_name
;
158 sdca_data
->num_functions
++;
163 void sdca_lookup_functions(struct sdw_slave
*slave
)
165 struct device
*dev
= &slave
->dev
;
166 struct acpi_device
*adev
= to_acpi_device_node(dev
->fwnode
);
169 dev_info(dev
, "No matching ACPI device found, ignoring peripheral\n");
172 acpi_dev_for_each_child(adev
, find_sdca_function
, &slave
->sdca_data
);
174 EXPORT_SYMBOL_NS(sdca_lookup_functions
, "SND_SOC_SDCA");
176 MODULE_LICENSE("Dual BSD/GPL");
177 MODULE_DESCRIPTION("SDCA library");